<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 6.0.0">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">



<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.3/css/all.min.css" integrity="sha256-2H3fkXt6FEmrReK448mDVGKb3WW2ZZw35gI7vqHOE4Y=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/animate.css@3.1.1/animate.min.css" integrity="sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE=" crossorigin="anonymous">

<script class="next-config" data-name="main" type="application/json">{"hostname":"example.com","root":"/","images":"/images","scheme":"Gemini","version":"8.7.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":true,"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"Searching...","empty":"We didn't find any results for the search: ${query}","hits_time":"${hits} results found in ${time} ms","hits":"${hits} results found"},"path":"/search.xml","localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false}}</script><script src="/js/config.js"></script>
<meta name="description" content="Never stop learning">
<meta property="og:type" content="website">
<meta property="og:title" content="Xiaolong&#39;s Blog">
<meta property="og:url" content="http://example.com/page/3/index.html">
<meta property="og:site_name" content="Xiaolong&#39;s Blog">
<meta property="og:description" content="Never stop learning">
<meta property="og:locale" content="en_US">
<meta property="article:author" content="Xiaolong">
<meta name="twitter:card" content="summary">


<link rel="canonical" href="http://example.com/page/3/">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":true,"isPost":false,"lang":"en","comments":"","permalink":"","path":"page/3/index.html","title":""}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>Xiaolong's Blog</title>
  




  <noscript>
    <link rel="stylesheet" href="/css/noscript.css">
  </noscript>
</head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="Toggle navigation bar" role="button">
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <i class="logo-line"></i>
      <h1 class="site-title">Xiaolong's Blog</h1>
      <i class="logo-line"></i>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>



<nav class="site-nav">
  <ul class="main-menu menu">
        <li class="menu-item menu-item-home"><a href="/" rel="section"><i class="fa fa-home fa-fw"></i>Home</a></li>
        <li class="menu-item menu-item-tags"><a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>Tags</a></li>
        <li class="menu-item menu-item-archives"><a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>Archives</a></li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>Search
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup"><div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off" maxlength="80"
           placeholder="Searching..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close" role="button">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div class="search-result-container no-result">
  <div class="search-result-icon">
    <i class="fa fa-spinner fa-pulse fa-5x"></i>
  </div>
</div>

    </div>
  </div>

</div>
        
  
  <div class="toggle sidebar-toggle" role="button">
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
  </div>

  <aside class="sidebar">

    <div class="sidebar-inner sidebar-overview-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          Table of Contents
        </li>
        <li class="sidebar-nav-overview">
          Overview
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-overview">
            <div class="site-author site-overview-item animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Xiaolong"
      src="/images/lion.jpg">
  <p class="site-author-name" itemprop="name">Xiaolong</p>
  <div class="site-description" itemprop="description">Never stop learning</div>
</div>
<div class="site-state-wrap site-overview-item animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/archives/">
          <span class="site-state-item-count">45</span>
          <span class="site-state-item-name">posts</span>
        </a>
      </div>
      <div class="site-state-item site-state-tags">
          <a href="/tags/">
        <span class="site-state-item-count">17</span>
        <span class="site-state-item-name">tags</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author site-overview-item animated">
      <span class="links-of-author-item">
        <a href="https://github.com/drwna" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;drwna" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
  </div>



          </div>
        </div>
      </div>
        <div class="back-to-top animated" role="button" aria-label="Back to top">
          <i class="fa fa-arrow-up"></i>
          <span>0%</span>
        </div>
    </div>
  </aside>
  <div class="sidebar-dimmer"></div>


    </header>

    
  <div class="reading-progress-bar"></div>

  <a href="https://github.com/Drwna" class="github-corner" title="Follow me on GitHub" aria-label="Follow me on GitHub" rel="noopener" target="_blank"><svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


    <div class="main-inner index posts-expand">

    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/10/14/07/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/lion.jpg">
      <meta itemprop="name" content="Xiaolong">
      <meta itemprop="description" content="Never stop learning">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Xiaolong's Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/10/14/07/" class="post-title-link" itemprop="url">webpack demo</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Posted on</span>

      <time title="Created: 2021-10-14 16:51:07" itemprop="dateCreated datePublished" datetime="2021-10-14T16:51:07+08:00">2021-10-14</time>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h2 id="webpack"><a href="#webpack" class="headerlink" title="webpack"></a><strong>webpack</strong></h2><p><a target="_blank" rel="noopener" href="https://gitee.com/draganet/webpack-demo-1">webpack-demo</a></p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">yarn init</span><br><span class="line">yarn add webpack webpack-cli --dev</span><br><span class="line"></span><br><span class="line">npx webpack --version</span><br></pre></td></tr></table></figure>

<p>在 package.json 中添加</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">&quot;scripts&quot;</span>: &#123;</span><br><span class="line">    <span class="string">&quot;build&quot;</span>: <span class="string">&quot;rm -rf dist &amp;&amp; webpack&quot;</span>,</span><br><span class="line">    <span class="string">&quot;start&quot;</span>: <span class="string">&quot;webpack serve --open&quot;</span></span><br><span class="line">  &#125;,</span><br></pre></td></tr></table></figure>



<h2 id="webpack-dev-server"><a href="#webpack-dev-server" class="headerlink" title="webpack-dev-server"></a>webpack-dev-server</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add webpack-dev-server --dev</span><br></pre></td></tr></table></figure>

<p>在 webpage.config.js 中添加</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">devtool: <span class="string">&#x27;inline-source-map&#x27;</span>,</span><br><span class="line">devServer: &#123;</span><br><span class="line">  static: <span class="string">&#x27;./dist&#x27;</span>,</span><br><span class="line">&#125;,</span><br></pre></td></tr></table></figure>



<h2 id="html-webpack-plugin"><a href="#html-webpack-plugin" class="headerlink" title="html-webpack-plugin"></a>html-webpack-plugin</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add html-webpack-plugin --devex</span><br></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">const HtmlWebpackPlugin = require(<span class="string">&#x27;html-webpack-plugin&#x27;</span>);</span><br><span class="line">const path = require(<span class="string">&#x27;path&#x27;</span>);</span><br><span class="line"></span><br><span class="line">module.exports = &#123;</span><br><span class="line">  entry: <span class="string">&#x27;index.js&#x27;</span>,</span><br><span class="line">  output: &#123;</span><br><span class="line">    path: path.resolve(__dirname, <span class="string">&#x27;./dist&#x27;</span>),</span><br><span class="line">    filename: <span class="string">&#x27;index.[contenthash].js&#x27;</span></span><br><span class="line">  &#125;,</span><br><span class="line">  plugins: [new HtmlWebpackPlugin(&#123;</span><br><span class="line">  	title: <span class="string">&#x27;My App&#x27;</span>,</span><br><span class="line">  	template: <span class="string">&#x27;src/assets/index.html&#x27;</span></span><br><span class="line">  &#125;)],</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>



<h2 id="css-loader"><a href="#css-loader" class="headerlink" title="css-loader"></a>css-loader</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add css-loader --dev</span><br></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">module</span>: &#123;</span><br><span class="line">    <span class="attr">rules</span>: [</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">test</span>: <span class="regexp">/\.css$/i</span>,</span><br><span class="line">        <span class="attr">use</span>: [<span class="string">&quot;style-loader&quot;</span>, <span class="string">&quot;css-loader&quot;</span>],</span><br><span class="line">      &#125;,</span><br><span class="line">    ],</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>



<h2 id="style-loader"><a href="#style-loader" class="headerlink" title="style-loader"></a>style-loader</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add style-loader --dev</span><br></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">module</span>: &#123;</span><br><span class="line">    <span class="attr">rules</span>: [</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">test</span>: <span class="regexp">/\.css$/i</span>,</span><br><span class="line">        <span class="attr">use</span>: [<span class="string">&quot;style-loader&quot;</span>, <span class="string">&quot;css-loader&quot;</span>],</span><br><span class="line">      &#125;,</span><br><span class="line">    ],</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>



<h2 id="mini-css-extract-plugin"><a href="#mini-css-extract-plugin" class="headerlink" title="mini-css-extract-plugin"></a>mini-css-extract-plugin</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add mini-css-extract-plugin --dev</span><br></pre></td></tr></table></figure>

<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title class_">MiniCssExtractPlugin</span> = <span class="built_in">require</span>(<span class="string">&quot;mini-css-extract-plugin&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">  <span class="attr">plugins</span>: [<span class="keyword">new</span> <span class="title class_">MiniCssExtractPlugin</span>(&#123;</span><br><span class="line">     <span class="attr">filename</span>: <span class="string">&#x27;[name].[contenthash].css&#x27;</span></span><br><span class="line">  &#125;)],</span><br><span class="line">  <span class="attr">module</span>: &#123;</span><br><span class="line">    <span class="attr">rules</span>: [</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">test</span>: <span class="regexp">/\.css$/i</span>,</span><br><span class="line">        <span class="attr">use</span>: [<span class="title class_">MiniCssExtractPlugin</span>.<span class="property">loader</span>, <span class="string">&quot;css-loader&quot;</span>],</span><br><span class="line">      &#125;</span><br><span class="line">    ]</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>




<h2 id="sass-loader"><a href="#sass-loader" class="headerlink" title="sass-loader"></a>sass-loader</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add sass dart-sass --dev</span><br></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">test</span>: /\.scss$/i,</span><br><span class="line">use: [</span><br><span class="line">    <span class="string">&quot;style-loader&quot;</span>,</span><br><span class="line">    <span class="string">&quot;css-loader&quot;</span>,</span><br><span class="line">    &#123;</span><br><span class="line">     loader: <span class="string">&quot;sass-loader&quot;</span>,</span><br><span class="line">     options: &#123; implementation: require(<span class="string">&quot;dart-sass&quot;</span>) &#125;</span><br><span class="line">    &#125;</span><br><span class="line">]</span><br></pre></td></tr></table></figure>



<h2 id="less-loader"><a href="#less-loader" class="headerlink" title="less-loader"></a>less-loader</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add less less-loader --dev</span><br></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">test</span>: /\.less$/i,</span><br><span class="line">use: [<span class="string">&quot;style-loader&quot;</span>, <span class="string">&quot;css-loader&quot;</span>, <span class="string">&quot;less-loader&quot;</span>]</span><br></pre></td></tr></table></figure>



<h2 id="stylus-loader"><a href="#stylus-loader" class="headerlink" title="stylus-loader"></a>stylus-loader</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add stylus stylus-loader --dev</span><br></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">test</span>: /\.styl$/i,</span><br><span class="line">use: [<span class="string">&quot;style-loader&quot;</span>, <span class="string">&quot;css-loader&quot;</span>, <span class="string">&quot;stylus-loader&quot;</span>]</span><br></pre></td></tr></table></figure>



<h2 id="file-loader"><a href="#file-loader" class="headerlink" title="file-loader"></a>file-loader</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn add file-loader --dev</span><br></pre></td></tr></table></figure>

<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">test</span>: /\.(png|svg|jpg|gif)$/,</span><br><span class="line">      use: [<span class="string">&quot;file-loader&quot;</span>]</span><br></pre></td></tr></table></figure>





<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/xiaolinlife/article/details/106533080?utm_medium=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~default-1.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~CTRLIST~default-1.no_search_link">path.resolve和__dirname</a></p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/10/07/44/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/lion.jpg">
      <meta itemprop="name" content="Xiaolong">
      <meta itemprop="description" content="Never stop learning">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Xiaolong's Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/10/07/44/" class="post-title-link" itemprop="url">AJAX</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Posted on</span>

      <time title="Created: 2021-10-07 23:02:44" itemprop="dateCreated datePublished" datetime="2021-10-07T23:02:44+08:00">2021-10-07</time>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h2 id="异步"><a href="#异步" class="headerlink" title="异步"></a>异步</h2><ul>
<li><p><strong>如果能直接拿到将结果</strong></p>
<p>那就是同步</p>
<p>比如你在医院挂号，你拿到号才会离开窗口</p>
<p>同步任务可能消耗 10 毫秒，也可能需要 3 秒</p>
<p>总之不拿到结果你是不会离开的，这就是同步</p>
</li>
<li><p><strong>如果不能直接拿到结果</strong></p>
<p>那就异步</p>
<p>比如你在餐厅门口等位，你拿到号后可以去干别的事比如逛街</p>
<p>你可以每 10 分钟取餐厅问一下排到自己了没（轮询）</p>
<p>也可以扫码用微信接受通知（回调）</p>
</li>
</ul>
<h2 id="异步举例"><a href="#异步举例" class="headerlink" title="异步举例"></a>异步举例</h2><ul>
<li><p><strong>以 AJAX 为例</strong></p>
<p><code>request.send()</code> 之后，并不能直接得到 response</p>
<p>用 <code>console.log(request.response)</code> 试试</p>
<p>必须等到 readyState 变为 4 后，浏览器才会<strong>回头调用</strong> <code>request.onreadystatechange</code> 函数</p>
<p>我们才能得到 <code>request.response</code></p>
<p>这就跟餐厅给你发微信提醒的过程类似</p>
</li>
<li><p><strong>回调 callback</strong></p>
<p>你写给自己用的函数，不是回调</p>
<p>你写给别人用的函数，就是回调</p>
<p><code>request.onreadystatechange</code> 就是写个浏览器调用的</p>
<p>意思是你（浏览器）回头调用一下这个函数</p>
</li>
<li><p>简单来理解就是：同步按你的代码顺序执行，异步不按照代码顺序执行，异步的执行效率更高。</p>
</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">getJSON.<span class="property">onclick</span> = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> request = <span class="keyword">new</span> <span class="title class_">XMLHttpRequest</span>();</span><br><span class="line">    request.<span class="title function_">open</span>(<span class="string">&#x27;GET&#x27;</span>, <span class="string">&#x27;/5.json&#x27;</span>);</span><br><span class="line">    request.<span class="property">onreadystatechange</span> = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (request.<span class="property">readyState</span> === <span class="number">4</span> &amp;&amp; request.<span class="property">status</span> === <span class="number">200</span>) &#123;</span><br><span class="line">            <span class="keyword">const</span> object = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(request.<span class="property">response</span>);</span><br><span class="line">            myName.<span class="property">textContent</span> = object.<span class="property">name</span>;</span><br><span class="line">	        <span class="variable language_">console</span>.<span class="title function_">log</span>(request.<span class="property">response</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    request.<span class="title function_">send</span>();</span><br><span class="line">    <span class="comment">// console.log(request.resopne)</span></span><br><span class="line">    <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(request.<span class="property">response</span>);</span><br><span class="line">        <span class="comment">// 或者将 放在 request.onreadystatechange 函数中</span></span><br><span class="line">    &#125;, <span class="number">2000</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// request.send()执行完，再执行 request.onreadystatechange 函数</span></span><br><span class="line"><span class="comment">// 执行顺序为 response.open() =&gt; respone.send() =&gt; request.onreadystatechange</span></span><br></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/kis_wuyan/article/details/116231729">onreadystatechange 执行两次</a></p>
<h2 id="回调"><a href="#回调" class="headerlink" title="回调"></a>回调</h2><p>写了却不调用，给别人调用的函数，就是回调。需自行意会</p>
<p>函数例子：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">f1</span>(<span class="params"></span>) &#123;&#125;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">f2</span>(<span class="params">fn</span>) &#123;</span><br><span class="line">    <span class="title function_">fn</span>()</span><br><span class="line">&#125;</span><br><span class="line"><span class="title function_">f2</span>(f1)</span><br></pre></td></tr></table></figure>

<p>分析：</p>
<ol>
<li>我调用 f1 没有？</li>
<li>我把 f1 传给 f2 （别人）了没有？</li>
<li>f2 调用 f1 了没有？</li>
</ol>
<p>答：1. 调用了。2.穿了。3.f2 调用了 f1。</p>
<p>那么，f1 是不是我写给 f2 调用的函数？ 是。</p>
<p>所以，f1 是回调。</p>
<hr>


<p>例子2：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">f1</span>(<span class="params">x</span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(x)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">f2</span>(<span class="params">fn</span>)&#123;</span><br><span class="line">    <span class="title function_">fn</span>(<span class="string">&#x27;hello&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="title function_">f2</span>(f1)</span><br><span class="line"><span class="comment">// hello</span></span><br></pre></td></tr></table></figure>

<p>fn(‘hello’) 中的 fn 就是 f1 。</p>
<p>fn(’hello‘) 中的 ’hello’ 会被赋值给参数 x 。</p>
<p>所以 x 就是 ‘hello’。</p>
<h2 id="异步和回调的关系"><a href="#异步和回调的关系" class="headerlink" title="异步和回调的关系"></a>异步和回调的关系</h2><ul>
<li><p><strong>关联</strong></p>
<p>异步任务需要再得到结果时通知 JS 来拿结果</p>
<p>怎么通知？</p>
<p>可以让 JS 留一个函数地址给浏览器（电话号码）</p>
<p>异步任务完成时浏览器调用该函数即可（拨打电话）</p>
<p>同时把任务作为参数传给该函数（通知）</p>
<p>这个函数是我写给浏览器调用的，所以是回调函数</p>
</li>
<li><p><strong>区别</strong></p>
<p>异步任务需要用到回调函数来通知结果</p>
<p>但回调函数不一定只用在异步任务里</p>
<p>回调可以用到同步任务里</p>
<p><code>array.forEach(n=&gt;console.log(n))</code> 就是同步回调</p>
</li>
</ul>
<h2 id="判断同步异步"><a href="#判断同步异步" class="headerlink" title="判断同步异步"></a>判断同步异步</h2><p>如果一个函数的返回值处于</p>
<ul>
<li>setTimeout</li>
<li>AJAX（即 XMLHttpRequest）</li>
<li>AddEventListener</li>
</ul>
<p>这三个东西内部中，那么这个函数就是异步函数</p>
<p>还有其他 API 是异步的，遇到再说。</p>
<p>举例说明：</p>
<p>摇骰子, 随机打印出1-6 中的一个数</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> 摇骰子() &#123;</span><br><span class="line">  <span class="built_in">setTimeout</span>( <span class="function">() =&gt;</span> &#123; <span class="comment">// 箭头函数</span></span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">parseInt</span>(<span class="title class_">Math</span>.<span class="title function_">random</span>() * <span class="number">6</span>) + <span class="number">1</span>;</span><br><span class="line">  &#125;, <span class="number">1000</span>)</span><br><span class="line">  <span class="comment">// return undefined</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>分析：</p>
<p><code> 摇骰子（）</code> 里没有写 return，那就是 return undefined</p>
<p>箭头函数里有 return，返回真正结果</p>
<p>所以这是一个异步函数/异步任务。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> n = 摇骰子();</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(n)</span><br></pre></td></tr></table></figure>

<p>如何拿到异步结果？</p>
<p>用回调，写个函数，然后把函数地址给他</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">f1</span>(<span class="params">x</span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(x);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 然后要求 摇骰子函数 得到结果后 把结果作为参数 传给f1</span></span><br><span class="line"><span class="keyword">function</span> 摇骰子(fn)&#123;</span><br><span class="line">    <span class="built_in">setTimeout</span>( <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="title function_">fn</span>(<span class="built_in">parseInt</span>(<span class="title class_">Math</span>.<span class="title function_">random</span>() * <span class="number">6</span>) + <span class="number">1</span>)</span><br><span class="line">    &#125;, <span class="number">1000</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">摇骰子(f1); <span class="comment">// 结果</span></span><br></pre></td></tr></table></figure>

<p>简化为箭头函数</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">f1</span>(<span class="params">x</span>) &#123; </span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(x);</span><br><span class="line">&#125;</span><br><span class="line">摇骰子(f1);</span><br><span class="line"><span class="comment">// 改为</span></span><br><span class="line">摇骰子(<span class="function"><span class="params">x</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(x);</span><br><span class="line">&#125;);</span><br><span class="line"><span class="comment">// 再简化为</span></span><br><span class="line">摇骰子(<span class="variable language_">console</span>.<span class="property">log</span>);</span><br><span class="line"><span class="comment">// 如果参数个数不一致就不能这样简化，有个相关面试题</span></span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 面试题</span></span><br><span class="line"><span class="keyword">const</span> array = [<span class="string">&#x27;1&#x27;</span>, <span class="string">&#x27;2&#x27;</span>, <span class="string">&#x27;3&#x27;</span>].<span class="title function_">map</span>(<span class="built_in">parseInt</span>);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(array);</span><br><span class="line"><span class="comment">// 结果为 [1, NaN, NaN]</span></span><br><span class="line"><span class="comment">// parseInt(&#x27;1&#x27;, 0, arr) =&gt; 1</span></span><br><span class="line"><span class="comment">// parseInt(&#x27;2&#x27;, 1, arr) =&gt; NaN</span></span><br><span class="line"><span class="comment">// parseInt(&#x27;3&#x27;, 2, arr) =&gt; NaN</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> array = [<span class="string">&#x27;1&#x27;</span>, <span class="string">&#x27;2&#x27;</span> , <span class="string">&#x27;3&#x27;</span>].<span class="title function_">map</span>(<span class="function">(<span class="params">item, i , arr</span>) =&gt;</span> &#123;</span><br><span class="line">   <span class="keyword">return</span> <span class="built_in">parseInt</span>(item)</span><br><span class="line">&#125;);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(array)</span><br><span class="line"><span class="comment">// 正确结果 [1, 2, 3]</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 简写 永远使用箭头函数</span></span><br><span class="line"><span class="keyword">const</span> array = [<span class="string">&#x27;1&#x27;</span>, <span class="string">&#x27;2&#x27;</span>, <span class="string">&#x27;3&#x27;</span>].<span class="title function_">map</span>(<span class="function">(<span class="params">item</span>) =&gt;</span> <span class="built_in">parseInt</span>(item));</span><br></pre></td></tr></table></figure>



<h2 id="异步总结"><a href="#异步总结" class="headerlink" title="异步总结"></a>异步总结</h2><ul>
<li>异步任务不能拿到结果</li>
<li>于是我们传一个回调给异步任务</li>
<li>异步任务完成时调用回调</li>
<li>调用的时候把结果作为参数</li>
</ul>
<h2 id="异步任务两个结果，成功或失败"><a href="#异步任务两个结果，成功或失败" class="headerlink" title="异步任务两个结果，成功或失败"></a>异步任务两个结果，成功或失败</h2><h3 id="两个方法解决"><a href="#两个方法解决" class="headerlink" title="两个方法解决"></a>两个方法解决</h3><p><strong>方法一：回调接受两个参数</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">fs.<span class="title function_">readFile</span>(<span class="string">&#x27;./1.txt&#x27;</span>, <span class="function">(<span class="params">error, data</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">if</span>(error)&#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;失败&#x27;</span>); <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(data.<span class="title function_">toString</span>()) <span class="comment">// 成功</span></span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p><strong>方法二：两个回调</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">ajax</span>(<span class="string">&#x27;get&#x27;</span>, <span class="string">&#x27;/1.json&#x27;</span>, <span class="function"><span class="params">data</span> =&gt;</span> &#123;<span class="comment">/*成功回调*/</span>&#125;, <span class="function"><span class="params">error</span> =&gt;</span> &#123;<span class="comment">/*失败回调*/</span>&#125;)</span><br><span class="line"><span class="title function_">ajax</span>(<span class="string">&#x27;get&#x27;</span>, <span class="string">&#x27;/1.json&#x27;</span>,&#123;</span><br><span class="line">    <span class="attr">success</span>: <span class="function">() =&gt;</span> &#123;&#125;,</span><br><span class="line">    <span class="attr">fail</span>: <span class="function">() =&gt;</span> &#123;&#125;</span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// 接受一个对象，对象有两个 key 表示成功和失败</span></span><br></pre></td></tr></table></figure>



<h3 id="这些方法的不足"><a href="#这些方法的不足" class="headerlink" title="这些方法的不足"></a>这些方法的不足</h3><p>不管方法一还是方法二，都有问题</p>
<ol>
<li>不规范，名称五花八门，有人用 success + error，有人用 success + fail，done + fail</li>
<li>容易出现==回调地狱== ，代码变得看不懂</li>
<li>很难进行错无处理</li>
</ol>
<p><strong>回调地狱举例</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">getUser</span>( <span class="function"><span class="params">user</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="title function_">getGroups</span>(user, <span class="function">(<span class="params">groups</span>) =&gt;</span> &#123;</span><br><span class="line">        groups.<span class="title function_">forEach</span>( <span class="function">(<span class="params">g</span>) =&gt;</span> &#123;</span><br><span class="line">            g.<span class="title function_">filter</span>(<span class="function"><span class="params">x</span> =&gt;</span> x.<span class="property">ownerId</span> === user.<span class="property">id</span>)</span><br><span class="line">            .<span class="title function_">forEach</span>(<span class="function"><span class="params">x</span> =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(x))</span><br><span class="line">        &#125;)</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// 仅示例，这只是四层，二十层呢，代码会很难读</span></span><br></pre></td></tr></table></figure>

<center><img src="https://cdn.jsdelivr.net/gh/Drwna/image//images/Snipaste_2021-09-25_22-12-10.png" alt="Snipaste_2021-09-25_22-12-10" width="800px"></center><center style="font-size:14px;color:#C0C0C0;text-decoration:underline"> 吐槽回调地狱 来源网络</center> 



<h3 id="如何解决回调问题，用-Promise"><a href="#如何解决回调问题，用-Promise" class="headerlink" title="如何解决回调问题，用 Promise"></a>如何解决回调问题，用 Promise</h3><p>有什么办法能解决这三个问题：</p>
<ul>
<li>会犯回调的名字或顺序</li>
<li>拒绝回调地狱，让代码可读性更强</li>
<li>很方便地捕获错误</li>
</ul>
<blockquote>
<p>1976年，Daniel P.Friedman 和 David Wis 俩人提出 Promise 思想</p>
<p>后人基于此发明了 Future、Delay、Deferred等</p>
<p>前端结合 Promise 和 JS，制定了 <a target="_blank" rel="noopener" href="https://www.ituring.com.cn/article/66566">Promise/A+规范</a></p>
<p>该规范详细描述了 Promise 的原理和使用方法。</p>
</blockquote>
<h2 id="以-AJAX-的封装为例，来解释-Promise"><a href="#以-AJAX-的封装为例，来解释-Promise" class="headerlink" title="以 AJAX 的封装为例，来解释 Promise"></a>以 AJAX 的封装为例，来解释 Promise</h2><p><a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise MDN</a></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 示例</span></span><br><span class="line">ajax = <span class="function">(<span class="params">method, url, options</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> &#123;success, fail&#125; = option; <span class="comment">// 析构赋值</span></span><br><span class="line">    <span class="comment">// const succes = option.success;</span></span><br><span class="line">    <span class="comment">// const fail = option.fail;</span></span><br><span class="line">    <span class="keyword">const</span> request = <span class="keyword">new</span> <span class="title class_">XMLHttpRequest</span>();</span><br><span class="line">    request.<span class="title function_">open</span>(method, url);</span><br><span class="line">    request.<span class="property">onreadystatechange</span> = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (request.<span class="property">readyState</span> === <span class="number">4</span>) &#123;</span><br><span class="line">            <span class="comment">// 成功就调用 success，失败 fail</span></span><br><span class="line">            <span class="keyword">if</span> (request.<span class="property">status</span> &lt; <span class="number">400</span>) &#123;</span><br><span class="line">                success.<span class="title function_">call</span>(<span class="literal">null</span>, request.<span class="property">response</span>);</span><br><span class="line">            &#125;<span class="keyword">else</span> <span class="keyword">if</span> (request.<span class="property">status</span> &gt;= <span class="number">400</span>) &#123;</span><br><span class="line">                fail.<span class="title function_">call</span>(<span class="literal">null</span>, request, request.<span class="property">status</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    request.<span class="title function_">rend</span>();</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="title function_">ajax</span>(<span class="string">&#x27;get&#x27;</span>, <span class="string">&#x27;/xxx&#x27;</span>, &#123;</span><br><span class="line">    <span class="title function_">success</span>(<span class="params">response</span>)&#123;&#125;, <span class="comment">// function 缩写</span></span><br><span class="line">    <span class="comment">// success: function(response)&#123;&#125;</span></span><br><span class="line">    <span class="attr">fail</span>: <span class="function">(<span class="params">request, status</span>) =&gt;</span> &#123;&#125;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>



<p>Promise 写法：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 先改一下调用姿势</span></span><br><span class="line"><span class="title function_">ajax</span>(<span class="string">&#x27;get&#x27;</span>, <span class="string">&#x27;/xxx&#x27;</span>, &#123;</span><br><span class="line">    <span class="title function_">success</span>(<span class="params">response</span>)&#123;&#125;,</span><br><span class="line">    <span class="attr">fail</span>: <span class="function">(<span class="params">request, status</span>) =&gt;</span> &#123;&#125;</span><br><span class="line">&#125;)</span><br><span class="line"><span class="comment">// 上面用到了两个回调，还使用了 success 和 fail</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 改成 Promise 写法</span></span><br><span class="line"><span class="title function_">ajax</span>(<span class="string">&#x27;get&#x27;</span>, <span class="string">&#x27;/xxx&#x27;</span>)</span><br><span class="line">    .<span class="title function_">then</span>(<span class="function">(<span class="params">response</span>)=&gt;</span>&#123;&#125;, <span class="function">(<span class="params">request, status</span>)=&gt;</span>&#123;&#125; )</span><br><span class="line"><span class="comment">// 虽然也是回调</span></span><br><span class="line"><span class="comment">// 但是不需要经济 success 和 fail 了</span></span><br><span class="line"><span class="comment">// then 的第一个参数就是 success</span></span><br><span class="line"><span class="comment">// then 的第二个参数就是 fail</span></span><br></pre></td></tr></table></figure>

<p>请问 ajax() 返回了个啥 ？</p>
<p>返回了一个含有 .then() 方法的对象呗。</p>
<p>那么再请问如何得到这个含有 .then() 的对象呢 ？</p>
<p>那就要改造 ajax 的源码了。</p>
<p><code>return new Promise((resolve, reject) =&gt; &#123;&#125;)</code></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 修改 ajax</span></span><br><span class="line">ajax = <span class="function">(<span class="params">method, url, option</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">const</span> &#123;success, fail&#125; = option;</span><br><span class="line">        <span class="keyword">const</span> request = <span class="keyword">new</span> <span class="title class_">XMLHttpRequest</span>();</span><br><span class="line">        request.<span class="title function_">open</span>(methon, url);</span><br><span class="line">        request.<span class="property">onreadystatechange</span> = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="keyword">if</span>(request.<span class="property">readyState</span> === <span class="number">4</span>) &#123;</span><br><span class="line">                <span class="keyword">if</span>(request.<span class="property">status</span> &lt; <span class="number">400</span>) &#123;</span><br><span class="line">                    <span class="comment">// 成功</span></span><br><span class="line">                    resolve.<span class="title function_">call</span>(<span class="literal">null</span>, request.<span class="property">response</span>);</span><br><span class="line">                &#125;<span class="keyword">else</span> <span class="keyword">if</span>(request.<span class="property">status</span> &gt;= <span class="number">400</span>) &#123;</span><br><span class="line">                    <span class="comment">// s</span></span><br><span class="line">                    reject.<span class="title function_">call</span>(<span class="literal">null</span>, request);</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        request.<span class="title function_">send</span>();</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<p><strong>小结</strong></p>
<p>第一步：</p>
<ul>
<li><code>retrun new Promise((resolve, reject) =&gt; &#123;...&#125;)</code></li>
<li>任务成功则调用 <code>resolve(result)</code></li>
<li>任务失败则调用 <code>reject(error)</code></li>
<li>resolve 和 reject 会再去调用成功和失败函数</li>
</ul>
<p>第二步：</p>
<ul>
<li>使用 <code>.then(success, fail)</code>传入成功函数和失败函数</li>
</ul>
<hr>
<p>我们自己封装的 ajax 的缺点:</p>
<p>post 无法上传数据。request.send(这里可以上传数据)</p>
<p>不能设置请求头。request.setRequestHeader(key, value)</p>
<p>使用：</p>
<p> <a target="_blank" rel="noopener" href="https://www.jquery123.com/jQuery.ajax/">Jquery.ajax</a></p>
<p><a target="_blank" rel="noopener" href="http://www.axios-js.com/zh-cn/docs/">axios</a>(推荐)</p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/09/20/54/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/lion.jpg">
      <meta itemprop="name" content="Xiaolong">
      <meta itemprop="description" content="Never stop learning">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Xiaolong's Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/09/20/54/" class="post-title-link" itemprop="url">js排序</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Posted on</span>

      <time title="Created: 2021-09-20 23:27:54" itemprop="dateCreated datePublished" datetime="2021-09-20T23:27:54+08:00">2021-09-20</time>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h2 id="选择排序"><a href="#选择排序" class="headerlink" title="选择排序"></a>选择排序</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">minIndex</span> = (<span class="params">numbers</span>) =&gt; &#123;</span><br><span class="line">  <span class="keyword">var</span> index = <span class="number">0</span></span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">1</span>; i &lt; numbers.<span class="property">length</span>; i++) &#123;</span><br><span class="line">    <span class="keyword">if</span> (numbers[i] &lt; numbers[index]) &#123;</span><br><span class="line">      index = i</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> index</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">swap</span> = (<span class="params">array, i, j</span>) =&gt; &#123;</span><br><span class="line">  <span class="keyword">let</span> temp = array[i]</span><br><span class="line">  array[i] = array[j]</span><br><span class="line">  array[j] = temp</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">sort</span> = (<span class="params">numbers</span>) =&gt; &#123;</span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; numbers.<span class="property">length</span> - <span class="number">1</span>; i++) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`----`</span>)</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`i: <span class="subst">$&#123;i&#125;</span>`</span>)</span><br><span class="line">    <span class="keyword">let</span> index = <span class="title function_">minIndex</span>(numbers.<span class="title function_">slice</span>(i)) + i</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`index: <span class="subst">$&#123;index&#125;</span>`</span>)</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`min: <span class="subst">$&#123;numbers[index]&#125;</span>`</span>)</span><br><span class="line">    <span class="keyword">if</span> (index !== i) &#123;</span><br><span class="line">      <span class="title function_">swap</span>(numbers, index, i)</span><br><span class="line">      <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`swap <span class="subst">$&#123;index&#125;</span>: <span class="subst">$&#123;i&#125;</span>`</span>)</span><br><span class="line">      <span class="variable language_">console</span>.<span class="title function_">log</span>(numbers)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> numbers</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="title function_">sort</span>([<span class="number">2</span>, <span class="number">55</span>, <span class="number">78</span>, <span class="number">99</span>, <span class="number">88</span>, <span class="number">654</span>])</span><br><span class="line"></span><br></pre></td></tr></table></figure>



<h2 id="快速排序"><a href="#快速排序" class="headerlink" title="快速排序"></a>快速排序</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title function_">quickSort</span> = arr =&gt; &#123;</span><br><span class="line">  <span class="keyword">if</span> (arr.<span class="property">length</span> &lt;= <span class="number">1</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> arr</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">let</span> pivotIndex = <span class="title class_">Math</span>.<span class="title function_">floor</span>(arr.<span class="property">length</span> / <span class="number">2</span>)</span><br><span class="line">  <span class="keyword">let</span> pivot = arr.<span class="title function_">splice</span>(pivotIndex, <span class="number">1</span>)[<span class="number">0</span>]</span><br><span class="line">  <span class="keyword">let</span> left = [],</span><br><span class="line">    right = []</span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; arr.<span class="property">length</span>; i++) &#123;</span><br><span class="line">    <span class="keyword">if</span> (arr[i] &lt; pivot) &#123;</span><br><span class="line">      left.<span class="title function_">push</span>(arr[i])</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      right.<span class="title function_">push</span>(arr[i])</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> <span class="title function_">quickSort</span>(left).<span class="title function_">concat</span>([pivot], <span class="title function_">quickSort</span>(right))</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="title function_">quickSort</span>([<span class="number">24</span>, <span class="number">946</span>, <span class="number">9</span>, <span class="number">45</span>, <span class="number">6</span>])</span><br><span class="line"></span><br></pre></td></tr></table></figure>



<h2 id="归并排序"><a href="#归并排序" class="headerlink" title="归并排序"></a>归并排序</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title function_">mergeSort</span> = arr =&gt; &#123;</span><br><span class="line">  <span class="keyword">if</span> (arr.<span class="property">length</span> === <span class="number">1</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> arr</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">let</span> left = arr.<span class="title function_">slice</span>(<span class="number">0</span>, <span class="title class_">Math</span>.<span class="title function_">floor</span>(arr.<span class="property">length</span> / <span class="number">2</span>))</span><br><span class="line">  <span class="keyword">let</span> right = arr.<span class="title function_">slice</span>(<span class="title class_">Math</span>.<span class="title function_">floor</span>(arr.<span class="property">length</span> / <span class="number">2</span>))</span><br><span class="line">  <span class="keyword">return</span> <span class="title function_">merge</span>(<span class="title function_">mergeSort</span>(left), <span class="title function_">mergeSort</span>(right))</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">merge</span> = (<span class="params">a, b</span>) =&gt; &#123;</span><br><span class="line">  <span class="keyword">if</span> (a.<span class="property">length</span> === <span class="number">0</span>) <span class="keyword">return</span> b</span><br><span class="line">  <span class="keyword">if</span> (b.<span class="property">length</span> === <span class="number">0</span>) <span class="keyword">return</span> a</span><br><span class="line">  <span class="keyword">return</span> a[<span class="number">0</span>] &gt; b[<span class="number">0</span>] ? [b[<span class="number">0</span>]].<span class="title function_">concat</span>(<span class="title function_">merge</span>(a, b.<span class="title function_">slice</span>(<span class="number">1</span>))) : [a[<span class="number">0</span>]].<span class="title function_">concat</span>(<span class="title function_">merge</span>(a.<span class="title function_">slice</span>(<span class="number">1</span>), b))</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="title function_">mergeSort</span>([<span class="number">23</span>, <span class="number">8</span>, <span class="number">4</span>, <span class="number">99</span>, <span class="number">12</span>])</span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>



<h2 id="计数排序"><a href="#计数排序" class="headerlink" title="计数排序"></a>计数排序</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> <span class="title function_">countingSort</span> = arr =&gt; &#123;</span><br><span class="line">  <span class="keyword">let</span> hashTable = &#123;&#125;,</span><br><span class="line">    max = <span class="number">0</span>,</span><br><span class="line">    result = []</span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; arr.<span class="property">length</span>; i++) &#123;</span><br><span class="line">    <span class="keyword">if</span> (!(arr[i] <span class="keyword">in</span> hashTable)) &#123;</span><br><span class="line">      hashTable[arr[i]] = <span class="number">1</span></span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      hashTable[arr[i]] += <span class="number">1</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span> (arr[i] &gt; max) &#123;</span><br><span class="line">      max = arr[i]</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">for</span> (<span class="keyword">let</span> j = <span class="number">0</span>; j &lt;= max; j++) &#123;</span><br><span class="line">    <span class="keyword">if</span> (j <span class="keyword">in</span> hashTable) &#123;</span><br><span class="line">      <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; hashTable[j]; i++) &#123;</span><br><span class="line">        result.<span class="title function_">push</span>(j)</span><br><span class="line"></span><br><span class="line">      &#125;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> result</span><br><span class="line">&#125;</span><br><span class="line"><span class="title function_">countingSort</span>([<span class="number">2</span>, <span class="number">9</span>, <span class="number">5</span>, <span class="number">7</span>])</span><br><span class="line"></span><br></pre></td></tr></table></figure>



<h2 id="时间复杂度对比"><a href="#时间复杂度对比" class="headerlink" title="时间复杂度对比"></a>时间复杂度对比</h2><p>选择排序    O(n^2)</p>
<p>快速排序    O(n * log2 n)</p>
<p>归并排序    O(n * log2 n)</p>
<p>计数排序    O(n + max)</p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/09/19/48/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/lion.jpg">
      <meta itemprop="name" content="Xiaolong">
      <meta itemprop="description" content="Never stop learning">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Xiaolong's Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/09/19/48/" class="post-title-link" itemprop="url">浅析MVC</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Posted on</span>

      <time title="Created: 2021-09-19 22:54:48" itemprop="dateCreated datePublished" datetime="2021-09-19T22:54:48+08:00">2021-09-19</time>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h2 id="MVC是什么"><a href="#MVC是什么" class="headerlink" title="MVC是什么"></a>MVC是什么</h2><p>MVC 是一种设计模式，他将应用分为三个部分：</p>
<p>M 是 Model，数据模型，负责数据相关的任务</p>
<p>V 是 View，视图，负责用户界面</p>
<p>C 是 Controller，控制器，负责监听用户事件，然后调用 M 和 V 更新数据和视图</p>
<h2 id="伪代码实现-MVC"><a href="#伪代码实现-MVC" class="headerlink" title="伪代码实现 MVC"></a>伪代码实现 MVC</h2><p>M</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">M = &#123;</span><br><span class="line">    <span class="attr">data</span>: &#123; 程序需要操作的数据或信息 &#125;，</span><br><span class="line">    <span class="attr">create</span>: &#123; 增数据 &#125;,</span><br><span class="line">    <span class="attr">delete</span>: &#123; 删数据 &#125;,</span><br><span class="line">    <span class="title function_">update</span>(<span class="params">data</span>) &#123; </span><br><span class="line">       <span class="title class_">Object</span>.<span class="title function_">assign</span>(m.<span class="property">data</span>, data) <span class="comment">// 使用新数据替换旧数据</span></span><br><span class="line">       eventBus.<span class="title function_">trigger</span>(<span class="string">&#x27;m:upate&#x27;</span>) <span class="comment">// eventBus 触发&#x27;m:update&#x27;信息, 通知 View 刷新 </span></span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">get</span>:&#123; 获取数据 &#125; </span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p>V</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">V = &#123;</span><br><span class="line">    <span class="attr">el</span>: 需要刷新的元素,</span><br><span class="line">    <span class="attr">html</span>: <span class="string">`显示在页面上的内容`</span></span><br><span class="line">    <span class="title function_">init</span>(<span class="params"></span>)&#123;</span><br><span class="line">        v.<span class="property">el</span>: 需要刷新的元素</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">render</span>(<span class="params"></span>)&#123; 刷新页面 &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>C</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">C = &#123;</span><br><span class="line">    <span class="title function_">init</span>(<span class="params"></span>)&#123;</span><br><span class="line">        v.<span class="title function_">init</span>() <span class="comment">//初始化 V</span></span><br><span class="line">        v.<span class="title function_">render</span>() <span class="comment">// 第一次渲染页面</span></span><br><span class="line">        c.<span class="title function_">autoBindEvents</span>() <span class="comment">// 自动的事件绑定</span></span><br><span class="line">        eventBus.<span class="title function_">on</span>(<span class="string">&#x27;m:update&#x27;</span>,<span class="function">()=&gt;</span>&#123;v.<span class="title function_">render</span>()&#125; <span class="comment">// 当 enentsBus 触发 &#x27;m:update&#x27; 时 V 刷新</span></span><br><span class="line">    &#125;，</span><br><span class="line">    <span class="attr">events</span>:&#123;事件以哈希表的方式记录存储&#125;,</span><br><span class="line">    <span class="title function_">method</span>(<span class="params"></span>)&#123;</span><br><span class="line">        data = 新数据</span><br><span class="line">        m.<span class="title function_">update</span>(data)</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">autoBindEvents</span>(<span class="params"></span>)&#123;自动绑定事件&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://github.com/Drwna/MVC-demo">mvc-demo</a></p>
<h2 id="EventBus"><a href="#EventBus" class="headerlink" title="EventBus"></a>EventBus</h2><p>EventBus 又称为事件总线,可以用来进行组件之间的监听和通信。</p>
<p>比如说当 Model 模块中的数据发生更新，触发了 EventBus 上的某个事件，而 Controller 恰好在监听这个事件，当这个事件触发时，Controller 就知道 Model 中的数据发生了更新了，从而做出一些反应</p>
<p>常用 API</p>
<ul>
<li>EventBus.on() 监听事件</li>
<li>EventBus.trigger() 触发事件</li>
<li>EventBus.off() 解绑事件</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">EventBus</span> &#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">_eventBus</span> = $(<span class="variable language_">window</span>)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">on</span>(<span class="params">eventName, fn</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">_eventBus</span>.<span class="title function_">on</span>(eventName, fn)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">trigger</span>(<span class="params">eventName, data</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">_eventBus</span>.<span class="title function_">trigger</span>(eventName, data)</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="title function_">off</span>(<span class="params">eventName, fn</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">_eventBus</span>.<span class="title function_">off</span>(eventName, fn)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h2 id="表驱动编程"><a href="#表驱动编程" class="headerlink" title="表驱动编程"></a>表驱动编程</h2><p>《代码大全》对表驱动编程的描述：</p>
<blockquote>
<p>表驱动方法是一种使你可以在表中查找信息，而不必用逻辑语句（if 或 case）来把他们找出来的方法。事实上，任何信息都可以通过表来挑选。在简单的情况下，逻辑语句往往更简单而且更直接。但随着逻辑链的复杂，表就变得越来越富于吸引力了。</p>
</blockquote>
<p>表驱动编程的意义在于<strong>逻辑与数据的分离</strong>（类似于事件委托）</p>
<p>例如：if else</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">translate</span>(<span class="params">term</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (term === <span class="string">&#x27;1&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&#x27;一&#x27;</span></span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (term === <span class="string">&#x27;2&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&#x27;二&#x27;</span></span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (term === <span class="string">&#x27;3&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&#x27;三&#x27;</span></span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&#x27;？？？&#x27;</span>  </span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 如果想添加一个新的名词翻译，需要再添加一个if-else逻辑，例如：</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">translate</span>(<span class="params">term</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (term === <span class="string">&#x27;1&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&#x27;一&#x27;</span></span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (term === <span class="string">&#x27;2&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&#x27;二&#x27;</span></span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (term === <span class="string">&#x27;3&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&#x27;三&#x27;</span></span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (term === <span class="string">&#x27;4&#x27;</span>) &#123;   </span><br><span class="line">        <span class="comment">// 此处添加了一个新的名词翻译</span></span><br><span class="line">        <span class="keyword">return</span> <span class="string">&#x27;四&#x27;</span></span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="string">&#x27;？？？&#x27;</span>  </span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>



<p>改为表驱动</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">translate</span>(<span class="params">term</span>) &#123;</span><br><span class="line">    <span class="keyword">let</span> terms = &#123;</span><br><span class="line">        <span class="string">&#x27;1&#x27;</span>: <span class="string">&#x27;一&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;2&#x27;</span>: <span class="string">&#x27;二&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;3&#x27;</span>: <span class="string">&#x27;三&#x27;</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> terms[term];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 如果想添加一个新的名词翻译，只需要在 terms 中添加一个新的表项，不需要修改整个逻辑</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">translate</span>(<span class="params">term</span>) &#123;</span><br><span class="line">    <span class="keyword">let</span> terms = &#123;</span><br><span class="line">        <span class="string">&#x27;1&#x27;</span>: <span class="string">&#x27;一&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;2&#x27;</span>: <span class="string">&#x27;二&#x27;</span>,</span><br><span class="line">        <span class="string">&#x27;3&#x27;</span>: <span class="string">&#x27;三&#x27;</span></span><br><span class="line">        <span class="string">&#x27;4&#x27;</span>: <span class="string">&#x27;四&#x27;</span>   <span class="comment">// 添加一个新的名词翻译</span></span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> terms[term];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 示例二</span></span><br><span class="line">c = &#123;</span><br><span class="line">     <span class="attr">events</span>:&#123;</span><br><span class="line">         <span class="string">&#x27;click #add1&#x27;</span>:<span class="string">&#x27;add&#x27;</span>,</span><br><span class="line">         <span class="string">&#x27;click #minus1&#x27;</span>:<span class="string">&#x27;minus&#x27;</span>,</span><br><span class="line">         <span class="string">&#x27;click #mul2&#x27;</span>:<span class="string">&#x27;mul&#x27;</span>,</span><br><span class="line">         <span class="string">&#x27;click #divide2&#x27;</span>:<span class="string">&#x27;div&#x27;</span></span><br><span class="line">     &#125;,</span><br><span class="line">     <span class="title function_">autoBindEvents</span>(<span class="params"></span>)&#123;</span><br><span class="line">         <span class="keyword">for</span>(<span class="keyword">let</span> key <span class="keyword">in</span> c.<span class="property">events</span>)&#123;</span><br><span class="line">             <span class="keyword">const</span> value = c[c.<span class="property">events</span>[key]]</span><br><span class="line">             <span class="keyword">const</span> spaceIndex = key.<span class="title function_">indexOf</span>(<span class="string">&#x27; &#x27;</span>)</span><br><span class="line">             <span class="keyword">const</span> part1 = key.<span class="title function_">slice</span>(<span class="number">0</span>, spaceIndex)</span><br><span class="line">             <span class="keyword">const</span> part2 = key.<span class="title function_">slice</span>(spaceIndex + <span class="number">1</span>)</span><br><span class="line">             v.<span class="property">el</span>.<span class="title function_">on</span>(part1,part2,value)</span><br><span class="line">         &#125;</span><br><span class="line">     &#125;</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>

<p>转自<a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/259806449">表驱动编程</a></p>
<h2 id="模块化"><a href="#模块化" class="headerlink" title="模块化"></a>模块化</h2><p><a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Modules">JavaScript modules 模块 MDN</a></p>
<p>模块就是实现特定功能的一组方法,而模块化是将模块的代码创造自己的作用域，只向外部暴露公开的方法和变量，而这些方法之间高度解耦。</p>
<p>一个应用的不同的功能分离成几个模块，需要什么功能就加载相应的模块。</p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/09/17/37/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/lion.jpg">
      <meta itemprop="name" content="Xiaolong">
      <meta itemprop="description" content="Never stop learning">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Xiaolong's Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/09/17/37/" class="post-title-link" itemprop="url">JS对象分类</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Posted on</span>

      <time title="Created: 2021-09-17 12:27:37" itemprop="dateCreated datePublished" datetime="2021-09-17T12:27:37+08:00">2021-09-17</time>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h2 id="一个小程序，输出各种形状的面积和周长"><a href="#一个小程序，输出各种形状的面积和周长" class="headerlink" title="一个小程序，输出各种形状的面积和周长"></a>一个小程序，输出各种形状的面积和周长</h2><h3 id="一"><a href="#一" class="headerlink" title="一"></a>一</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 正方形 边长、面积、周长</span></span><br><span class="line"><span class="keyword">let</span> square = &#123;</span><br><span class="line">    <span class="attr">width</span>: <span class="number">5</span>,</span><br><span class="line">    <span class="title function_">getArea</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">width</span> * <span class="variable language_">this</span>.<span class="property">width</span>;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">getLength</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">wdith</span> * <span class="number">4</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="二，生成12个正方形"><a href="#二，生成12个正方形" class="headerlink" title="二，生成12个正方形"></a>二，生成12个正方形</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> squareList = []</span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">let</span> i = <span class="number">0</span>; i&lt;<span class="number">12</span>; i++)&#123;</span><br><span class="line">    squareList[i] = &#123;</span><br><span class="line">        <span class="attr">width</span>: <span class="number">5</span>,</span><br><span class="line">        <span class="title function_">getArea</span>(<span class="params"></span>)&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">width</span> * <span class="variable language_">this</span>.<span class="property">width</span></span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="title function_">getLength</span>(<span class="params"></span>)&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">width</span> * <span class="number">4</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="三，width-是-5-和-6相间"><a href="#三，width-是-5-和-6相间" class="headerlink" title="三，width 是 5 和 6相间"></a>三，width 是 5 和 6相间</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> squareList = []</span><br><span class="line"><span class="keyword">let</span> widthList = [<span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>]</span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">let</span> i = <span class="number">0</span>; i&lt;<span class="number">12</span>; i++)&#123;</span><br><span class="line">    squareList[i] = &#123;</span><br><span class="line">        <span class="attr">width</span>: widthList[i],</span><br><span class="line">        <span class="title function_">getArea</span>(<span class="params"></span>)&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">width</span> * <span class="variable language_">this</span>.<span class="property">width</span>;</span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="title function_">getLength</span>(<span class="params"></span>)&#123;</span><br><span class="line">            <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">widht</span> * <span class="number">4</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="三，垃圾代码，浪费太多内存，画内存图"><a href="#三，垃圾代码，浪费太多内存，画内存图" class="headerlink" title="三，垃圾代码，浪费太多内存，画内存图"></a>三，垃圾代码，浪费太多内存，画内存图</h3><center><img src="https://cdn.jsdelivr.net/gh/Drwna/image//images/squareMemory.png" alt="squareMemory" "></center>



<h3 id="四，借助原型，将12个对象的共有属性放到原型里"><a href="#四，借助原型，将12个对象的共有属性放到原型里" class="headerlink" title="四，借助原型，将12个对象的共有属性放到原型里"></a>四，借助原型，将12个对象的共有属性放到原型里</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> squareList = []</span><br><span class="line"><span class="keyword">let</span> widthList = [<span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>]</span><br><span class="line"><span class="keyword">let</span> squarePrototype = &#123;</span><br><span class="line">    <span class="title function_">getArea</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">width</span> * <span class="variable language_">this</span>.<span class="property">width</span>;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">getLength</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">width</span> * <span class="number">4</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">let</span> i = <span class="number">0</span>; i&lt;<span class="number">12</span>; i++)&#123;</span><br><span class="line">    squareList[i] = <span class="title class_">Object</span>.<span class="title function_">create</span>(squarePrototype);</span><br><span class="line">    squareList[i].<span class="property">width</span> = widthList[i];</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 还是垃圾代码，创建 square 的代码太分散了</span></span><br></pre></td></tr></table></figure>



<h3 id="五，把代码抽离到一个函数里，然后调用函数"><a href="#五，把代码抽离到一个函数里，然后调用函数" class="headerlink" title="五，把代码抽离到一个函数里，然后调用函数"></a>五，把代码抽离到一个函数里，然后调用函数</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> squareList = []</span><br><span class="line"><span class="keyword">let</span> widthList = [<span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>]</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">createSquare</span>(<span class="params">width</span>)&#123; <span class="comment">// 此函数为叫做构造函数</span></span><br><span class="line">    <span class="keyword">let</span> obj = <span class="title class_">Object</span>.<span class="title function_">create</span>(squarePrototype);</span><br><span class="line">    <span class="comment">// 以 squarePrototype 为原型创建空对象</span></span><br><span class="line">    obj.<span class="property">width</span> = width;</span><br><span class="line">    <span class="keyword">return</span> obj;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> squarePrototype = &#123;</span><br><span class="line">    <span class="title function_">getArea</span>(<span class="params"></span>) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">width</span> * <span class="variable language_">this</span>.<span class="property">width</span>;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">getLength</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">width</span> * <span class="number">4</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">let</span> i = <span class="number">0</span>; i&lt;<span class="number">12</span>; i++)&#123;</span><br><span class="line">    squareList[i] = <span class="title function_">createSquare</span>(widthList[i]);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="六，函数和原型的结合"><a href="#六，函数和原型的结合" class="headerlink" title="六，函数和原型的结合"></a>六，函数和原型的结合</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 这段代码 几乎完美</span></span><br><span class="line"><span class="keyword">let</span> squareList = []</span><br><span class="line"><span class="keyword">let</span> widthList = [<span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>]</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">createSquare</span>(<span class="params">width</span>)&#123;</span><br><span class="line">    <span class="keyword">let</span> obj = <span class="title class_">Object</span>.<span class="title function_">create</span>(createSquare.<span class="property">squarePrototype</span>);</span><br><span class="line">    obj.<span class="property">width</span> = width;</span><br><span class="line">    <span class="keyword">return</span> obj</span><br><span class="line">&#125;</span><br><span class="line">createSquare.<span class="property">squarePrototype</span> = &#123; <span class="comment">//把原型放到函数上</span></span><br><span class="line">    <span class="title function_">getArea</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">width</span> * <span class="variable language_">this</span>.<span class="property">width</span>;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">getLength</span>(<span class="params"></span>)&#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">width</span> * <span class="number">4</span>;  </span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">constructor</span>: createSquare <span class="comment">// 互相引用方便通过原型找到构造函数</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">let</span> i = <span class="number">0</span>; i&lt;<span class="number">12</span>; i++)&#123;</span><br><span class="line">    squareList[i] = <span class="title function_">createSquare</span>(widthList[i]);</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(squareList[i].<span class="property">constructor</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h3 id="七，函数和原型（重写）"><a href="#七，函数和原型（重写）" class="headerlink" title="七，函数和原型（重写）"></a>七，函数和原型（重写）</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> squareList = []</span><br><span class="line"><span class="keyword">let</span> widthList =  [<span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">6</span>]</span><br><span class="line"></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Square</span>(<span class="params">width</span>)&#123; <span class="comment">// 构造函数</span></span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">width</span> = width;</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Square</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">getArea</span> = <span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">width</span> * <span class="variable language_">this</span>.<span class="property">width</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Square</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">getLength</span> = <span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">width</span> * <span class="number">4</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">let</span> i = <span class="number">0</span>; i&gt;<span class="number">12</span>; i++)&#123;</span><br><span class="line">    squareList[i] = <span class="keyword">new</span> <span class="title class_">Square</span>(widthList[i]);</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(squareList[i].<span class="property">constructor</span>);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 完美</span></span><br></pre></td></tr></table></figure>

<p>代码六七对比</p>
<center><img src="https://cdn.jsdelivr.net/gh/Drwna/image//images/Snipaste_2021-08-31_12-16-01.png" alt="Snipaste_2021-08-31_12-16-01"></center>



<h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><ul>
<li><strong>new X()</strong><ul>
<li>自动创建空对象</li>
<li>自动为空对象关联原型，原型地址指定为 X.prototype</li>
<li>自动将空对象作为 this 关键字运行构造函数</li>
<li>自动 return this</li>
</ul>
</li>
<li><strong>构造函数 X</strong><ul>
<li>X 函数本身负责给对象本身添加属性</li>
<li>X.prototype 对想负责保存对象那个的公用属性</li>
</ul>
</li>
</ul>
<p>题外话 代码规范：</p>
<ul>
<li><p>大小写</p>
<ul>
<li> 所有构造函数（专门用于创建对象的函数）首字母大写</li>
<li> 所有被构造出来的对象，首字母小写</li>
</ul>
</li>
<li><p>词性</p>
<ul>
<li>new 后面的函数，使用名词形式</li>
<li>如 new Person()、new Object()</li>
<li>其他函数，一般使用动词开头</li>
<li>如 createSquare(5)、createElement(‘div’)</li>
<li>…</li>
</ul>
</li>
</ul>
<p>原型公式：**<font color='yellow'>对象._<em>proto</em>_  === 其构造函数.protorype</font>**</p>
<h3 id="Square-最终版（存疑）"><a href="#Square-最终版（存疑）" class="headerlink" title="Square 最终版（存疑）"></a>Square 最终版（存疑）</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">Square</span>(<span class="params">width</span>)&#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">width</span> = width;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="title class_">Square</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">getArea</span> = <span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">width</span> * <span class="variable language_">this</span>.<span class="property">width</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Square</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">getLenth</span> = <span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">width</span> * <span class="number">4</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> square = <span class="keyword">new</span> <span class="title class_">Square</span>(<span class="number">5</span>);</span><br><span class="line">square.<span class="property">width</span>;</span><br><span class="line">square.<span class="title function_">getArea</span>();</span><br><span class="line">square.<span class="title function_">getLength</span>();</span><br></pre></td></tr></table></figure>



<h3 id="练习"><a href="#练习" class="headerlink" title="练习"></a>练习</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 圆形</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Circle</span>(<span class="params">radius</span>)&#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">radius</span> = radius;</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Circle</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">getArea</span> = <span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">radius</span> * <span class="number">2</span> * <span class="title class_">Math</span>.<span class="property">PI</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Circle</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">getLength</span> = <span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="title class_">Math</span>.<span class="title function_">pow</span>(<span class="variable language_">this</span>.<span class="property">radius</span>, <span class="number">2</span>) * <span class="title class_">Math</span>.<span class="property">PI</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> c1 = <span class="keyword">new</span> <span class="title class_">Circle</span>(<span class="number">10</span>);</span><br><span class="line">c1.<span class="title function_">getArea</span>();</span><br><span class="line">c1.<span class="title function_">getLength</span>();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 长方形</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Rect</span>(<span class="params">width, height</span>) &#123;</span><br><span class="line">  <span class="variable language_">this</span>.<span class="property">width</span> = width;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">height</span> = height</span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Rect</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">getArea</span> = <span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">  <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">width</span> * <span class="variable language_">this</span>.<span class="property">height</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="title class_">Rect</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">getLength</span> = <span class="keyword">function</span>(<span class="params"></span>)&#123;</span><br><span class="line">  <span class="keyword">return</span> (<span class="variable language_">this</span>.<span class="property">width</span> + <span class="variable language_">this</span>.<span class="property">height</span>) * <span class="number">2</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> r1 = <span class="keyword">new</span> <span class="title class_">Rect</span>(<span class="number">2</span>, <span class="number">3</span>)</span><br><span class="line">r1.<span class="title function_">getArea</span>()</span><br><span class="line">r1.<span class="title function_">getLength</span>()</span><br></pre></td></tr></table></figure>



<h2 id="对象分类"><a href="#对象分类" class="headerlink" title="对象分类"></a>对象分类</h2><h3 id="分类"><a href="#分类" class="headerlink" title="分类"></a>分类</h3><ul>
<li>理由一<ul>
<li>有很多对象拥有一样的属性和行为</li>
<li>需要把他们分为同一类</li>
<li>如 square 和 square1</li>
<li>这样创建类似对象的时候就很方便</li>
</ul>
</li>
<li>理由二<ul>
<li>但是还有很多对象拥有其他的属性和行为</li>
<li>所以就需要不同的分类</li>
<li>比如 Square / Circle / Rect 就是不同的分类</li>
<li>Array / Function 也是不同的分类</li>
<li>而 Object 创建出来的对象，是最没有特点的对象</li>
</ul>
</li>
</ul>
<p><strong>类型和类</strong></p>
<p>类型</p>
<blockquote>
<p>类型 JS 数据的分类，有七种</p>
<p>四基两空一对象，String，number，bool，symbol，null，undefined，Object</p>
</blockquote>
<p>类</p>
<blockquote>
<p>类是针对对象的分类, 有无数种</p>
<p>常见的有 Array、Function、Date、RegExp 等</p>
</blockquote>
<h3 id="数组对象"><a href="#数组对象" class="headerlink" title="数组对象"></a>数组对象</h3><p>定义一个数组</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> arr = [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]</span><br><span class="line"><span class="keyword">let</span> arr = <span class="keyword">new</span> <span class="title class_">Array</span>(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>) <span class="comment">//元素为 1，2，3</span></span><br><span class="line"><span class="keyword">let</span> arr = <span class="keyword">new</span> <span class="title class_">Array</span>(<span class="number">3</span>) <span class="comment">//长度为3</span></span><br></pre></td></tr></table></figure>

<p>数组对象自身的属性</p>
<ul>
<li><p>‘0’ / ‘1’ / ‘2’ / ‘length’</p>
</li>
<li><p>注意，属性名没有数字，只有字符串</p>
</li>
</ul>
<p>数组对象的共用属性</p>
<p>‘push’ / ‘pop’ / ‘shift’ / ‘unshift’ / ‘join’  等</p>
<h3 id="函数对象"><a href="#函数对象" class="headerlink" title="函数对象"></a>函数对象</h3><p>定义一个函数</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">fn</span>(<span class="params">x, y</span>)&#123;<span class="keyword">return</span> x + y;&#125;</span><br><span class="line"><span class="keyword">let</span> fn2 = <span class="keyword">function</span> <span class="title function_">fn</span>(<span class="params">x, y</span>) &#123;<span class="keyword">return</span> x + y&#125;</span><br><span class="line"><span class="keyword">let</span> <span class="title function_">fn</span> = (<span class="params">x, y</span>) =&gt; x+y</span><br><span class="line"><span class="keyword">let</span> fn = <span class="keyword">new</span> <span class="title class_">Function</span>(<span class="string">&#x27;x&#x27;</span>, <span class="string">&#x27;y&#x27;</span>,<span class="string">&#x27;return x+y&#x27;</span>)</span><br></pre></td></tr></table></figure>

<p>函数对象自身属性</p>
<p>‘name’ / ‘length’</p>
<p>函数对象共用属性</p>
<p>‘call’ / ‘apply’ / ‘bind’ 等</p>
<h3 id="JS-终极一问"><a href="#JS-终极一问" class="headerlink" title="JS 终极一问"></a>JS 终极一问</h3><p>window 是谁构造的</p>
<blockquote>
<p>Window</p>
<p>可以通过 constructor 属性看出构造者</p>
<p>验证：window.constructor</p>
<p>window._<em>proto</em>_ === Windows.prototype</p>
</blockquote>
<p>window.Object 是谁构造的</p>
<blockquote>
<p>window.Funcion</p>
<p>因为所有函数都是 window.Function 构造的</p>
<p>验证：window.Object.constructor === window.Function</p>
</blockquote>
<p>window.Function 是谁构造的</p>
<blockquote>
<p>window.Function</p>
<p>因为所有函数都是 window.Function 构造的</p>
<p>自己构造的自己？不是这样的，这是『上帝』的安排</p>
<p>浏览器构造了 Function，然后指定它的构造者是自己</p>
<p>验证：window.Function.constructor === window.Function</p>
</blockquote>
<h2 id="class"><a href="#class" class="headerlink" title="class"></a>class</h2><p>类是用于创建对象的模板。他们用代码封装数据以处理该数据。 ES6新语法</p>
<p>学习<a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes">class</a>、<a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Object_initializer#ECMAScript_6%E6%96%B0%E6%A0%87%E8%AE%B0">对象初始化</a>、<a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment">解构赋值</a></p>
<p><code>constructor</code> 是一种用于创建和初始化 class 创建的对象的特殊方法. </p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Square</span>&#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">width</span>)&#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">width</span> = width;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">getArea</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">width</span> * <span class="variable language_">this</span>.<span class="property">width</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">getLength</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">width</span> * <span class="number">4</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>class 引入更多概念</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Square</span>&#123;</span><br><span class="line">    <span class="keyword">static</span> x = <span class="number">1</span>; <span class="comment">// 静态</span></span><br><span class="line">	width = <span class="number">0</span>;</span><br><span class="line">	<span class="title function_">constructor</span>(<span class="params">width</span>)&#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">width</span> = width;</span><br><span class="line">    &#125;</span><br><span class="line">	<span class="title function_">getArea</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">width</span> * <span class="variable language_">this</span>.<span class="property">width</span>;</span><br><span class="line">    &#125;</span><br><span class="line">	<span class="title function_">getLength</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">width</span> * <span class="number">4</span>;</span><br><span class="line">    &#125;</span><br><span class="line">	<span class="keyword">get</span> <span class="title function_">area2</span>()&#123; <span class="comment">// 只读属性</span></span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">width</span> * <span class="variable language_">this</span>.<span class="property">width</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<p><strong>class 重写</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 重写 Circle</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Circle</span>&#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">radius</span>)&#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">radius</span> = radius;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">getArea</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="title class_">Math</span>.<span class="title function_">pow</span>(<span class="variable language_">this</span>.<span class="property">radius</span>,<span class="number">2</span>) * <span class="title class_">Math</span>.<span class="property">PI</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">getLength</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">radius</span> * <span class="number">2</span> * <span class="title class_">Math</span>.<span class="property">PI</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> c2 = <span class="keyword">new</span> <span class="title class_">Circle</span>(<span class="number">5</span>);</span><br><span class="line">c2.<span class="property">radius</span>;</span><br><span class="line">c2.<span class="title function_">getArea</span>();</span><br><span class="line">c2.<span class="title function_">getLength</span>();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 重写 Rect</span></span><br><span class="line"><span class="keyword">class</span> <span class="title class_">Rect</span>&#123;</span><br><span class="line">    <span class="title function_">constructor</span>(<span class="params">width, height</span>)&#123;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">width</span> = width;</span><br><span class="line">        <span class="variable language_">this</span>.<span class="property">height</span> = height;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">getArea</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">width</span> * <span class="variable language_">this</span>.<span class="property">height</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="title function_">getLength</span>(<span class="params"></span>)&#123;</span><br><span class="line">        <span class="keyword">return</span> (<span class="variable language_">this</span>.<span class="property">width</span> + <span class="variable language_">this</span>.<span class="property">height</span>) * <span class="number">2</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">let</span> r2 = <span class="keyword">new</span> <span class="title class_">Rect</span>(<span class="number">3</span>, <span class="number">4</span>);</span><br><span class="line">r2.<span class="property">width</span>;</span><br><span class="line">r2.<span class="property">height</span>;</span><br><span class="line">r2.<span class="title function_">getArea</span>();</span><br><span class="line">r2.<span class="title function_">getLength</span>();</span><br></pre></td></tr></table></figure>



<p><strong>class 中两种函数写法的区别</strong></p>
<p>这两种写法的意思完全不一样：</p>
<p>语法1：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span>&#123;</span><br><span class="line">    <span class="title function_">sayHi</span>(<span class="params">name</span>)&#123;&#125;</span><br><span class="line">    <span class="comment">// 等价于</span></span><br><span class="line">    <span class="attr">sayHi</span>: <span class="keyword">function</span>(<span class="params">name</span>)&#123;&#125; </span><br><span class="line">    <span class="comment">// 注意，一般我们不在这个语法里使用箭头函数</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">//等价于</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Person</span>(<span class="params"></span>)&#123;&#125;</span><br><span class="line"><span class="title class_">Person</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">sayHi</span> = <span class="keyword">function</span>(<span class="params">name</span>)&#123;&#125;</span><br></pre></td></tr></table></figure>

<p>语法2：注意冒号变成了等于号</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Person</span>&#123;</span><br><span class="line">  sayHi = <span class="function">(<span class="params">name</span>)=&gt;</span>&#123;&#125; <span class="comment">// 注意，一般我们不在这个语法里使用普通函数，多用箭头函数</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 等价于</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">Person</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="variable language_">this</span>.<span class="property">sayHi</span> = <span class="function">(<span class="params">name</span>)=&gt;</span>&#123;&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure>



<p>推荐阅读</p>
<ol>
<li><a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/35279244">方应杭：你可以不会 class，但是一定要学会 prototype</a></li>
<li><a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/23987456">方应杭：JS 的 new 到底是干什么的？</a></li>
<li><a target="_blank" rel="noopener" href="https://www.zhihu.com/question/56770432/answer/315342130">方应杭：JS 中 <strong>proto</strong> 和 prototype 存在的意义是什么？</a></li>
<li><a target="_blank" rel="noopener" href="http://frankfang.github.io/es-6-tutorials/">饥人谷整理的 ES6 所有新特性</a></li>
</ol>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/09/12/01/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/lion.jpg">
      <meta itemprop="name" content="Xiaolong">
      <meta itemprop="description" content="Never stop learning">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Xiaolong's Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/09/12/01/" class="post-title-link" itemprop="url">浅析jQuery设计思想</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Posted on</span>

      <time title="Created: 2021-09-12 14:50:01" itemprop="dateCreated datePublished" datetime="2021-09-12T14:50:01+08:00">2021-09-12</time>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h3 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h3><p>jQuery 是目前使用最广泛的 JavaScript 函数库</p>
<p>对于网页开发者来说，学会 jQuery 是必要的。因为它让你了解业界最通用的技术，为将来学习更高级的库打下基础，并且确实可以很轻松地做出许多复杂的效果。</p>
<p>jQuery 是一个高效、精简并且功能丰富的 JavaScript 工具库。它提供的 API 易于使用且兼容众多浏览器，这让诸如 HTML 文档遍历和操作、事件处理、动画和 Ajax 操作更加简单。</p>
<p>jQuery 的基本设计思想就是，<strong>选择某个网页元素，然后对其进行某种操作</strong></p>
<p>jQuery 的实质就是一个<strong>封装的 DOM 库</strong>。</p>
<blockquote>
<p>仿 jQuery 手写了一些简单的 api，有兴趣可以参考一下 <a target="_blank" rel="noopener" href="https://github.com/Drwna/dom-2">简易jQuery</a></p>
</blockquote>
<h3 id="选择网页元素"><a href="#选择网页元素" class="headerlink" title="选择网页元素"></a>选择网页元素</h3><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//jQuery中:jQuery() = $()</span></span><br><span class="line"><span class="comment">//将一个选择表达式，放进构造函数$()</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//选择表达式可以是CSS选择器</span></span><br><span class="line">$(<span class="variable language_">document</span>) <span class="comment">//选择整个文档对象</span></span><br><span class="line">$(<span class="string">&#x27;#myId&#x27;</span>) <span class="comment">//选择ID为myId的网页元素</span></span><br><span class="line">$(<span class="string">&#x27;div.myClass&#x27;</span>) <span class="comment">// 选择class为myClass的div元素</span></span><br><span class="line">$(<span class="string">&#x27;input[name=first]&#x27;</span>) <span class="comment">// 选择name属性等于first的input元素</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//也可以是jQuery特有的表达式</span></span><br><span class="line">$(<span class="string">&#x27;a:first&#x27;</span>) <span class="comment">//选择网页中第一个a元素</span></span><br><span class="line">$(<span class="string">&#x27;tr:odd&#x27;</span>) <span class="comment">//选择表格的奇数行</span></span><br><span class="line">$(<span class="string">&#x27;#myForm :input&#x27;</span>) <span class="comment">// 选择表单中的input元素</span></span><br><span class="line">$(<span class="string">&#x27;div:visible&#x27;</span>) <span class="comment">//选择可见的div元素</span></span><br><span class="line">$(<span class="string">&#x27;div:gt(2)&#x27;</span>) <span class="comment">// 选择所有的div元素，除了前三个</span></span><br><span class="line">$(<span class="string">&#x27;div:animated&#x27;</span>) <span class="comment">// 选择当前处于动画状态的div元素</span></span><br></pre></td></tr></table></figure>



<h3 id="精确选择范围"><a href="#精确选择范围" class="headerlink" title="精确选择范围"></a>精确选择范围</h3><p>思想：提供各种强大的过滤器，对结果集进行筛选，缩小选择结果</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">$(<span class="string">&#x27;div&#x27;</span>).<span class="title function_">has</span>(<span class="string">&#x27;p&#x27;</span>); <span class="comment">// 选择包含p元素的div元素</span></span><br><span class="line">$(<span class="string">&#x27;div&#x27;</span>).<span class="title function_">not</span>(<span class="string">&#x27;.myClass&#x27;</span>); <span class="comment">//选择class不等于myClass的div元素</span></span><br><span class="line">$(<span class="string">&#x27;div&#x27;</span>).<span class="title function_">filter</span>(<span class="string">&#x27;.myClass&#x27;</span>); <span class="comment">//选择class等于myClass的div元素</span></span><br><span class="line">$(<span class="string">&#x27;div&#x27;</span>).<span class="title function_">first</span>(); <span class="comment">//选择第1个div元素</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//也可以从当前元素出发，移动到附近的相关元素</span></span><br><span class="line">$(<span class="string">&#x27;div&#x27;</span>).<span class="title function_">next</span>(<span class="string">&#x27;p&#x27;</span>); <span class="comment">//选择div元素后面的第一个p元素</span></span><br><span class="line">$(<span class="string">&#x27;div&#x27;</span>).<span class="title function_">parent</span>(); <span class="comment">//选择div元素的父元素</span></span><br><span class="line">$(<span class="string">&#x27;div&#x27;</span>).<span class="title function_">closest</span>(<span class="string">&#x27;form&#x27;</span>); <span class="comment">//选择离div最近的那个form父元素</span></span><br><span class="line">$(<span class="string">&#x27;div&#x27;</span>).<span class="title function_">children</span>(); <span class="comment">//选择div的所有子元素</span></span><br><span class="line">$(<span class="string">&#x27;div&#x27;</span>).<span class="title function_">siblings</span>(); <span class="comment">//选择div的同级元素</span></span><br></pre></td></tr></table></figure>



<h3 id="复制、删除、创建元素"><a href="#复制、删除、创建元素" class="headerlink" title="复制、删除、创建元素"></a>复制、删除、创建元素</h3><ul>
<li>复制元素使用 <code>.clone()</code></li>
<li>删除元素使用 <code>.remove()</code> 和 <code>.detach()</code></li>
</ul>
<blockquote>
<p>两者区别：前者不保留被删除元素的事件，后者保留，有利于重新插入文档时使用</p>
</blockquote>
<ul>
<li>清空元素内容（但是不删除该元素）使用 <code>.empty()</code></li>
<li>创建元素只要把新元素直接传入jQuery的构造函数就行了</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">$(<span class="string">&#x27;&lt;p&gt;Hello&lt;/p&gt;&#x27;</span>);</span><br><span class="line">$(<span class="string">&#x27;&lt;li class=&quot;new&quot;&gt;new list item&lt;/li&gt;&#x27;</span>);</span><br><span class="line">$(<span class="string">&#x27;ul&#x27;</span>).<span class="title function_">append</span>(<span class="string">&#x27;&lt;li&gt;list item&lt;/li&gt;&#x27;</span>);</span><br></pre></td></tr></table></figure>



<h3 id="链式操作"><a href="#链式操作" class="headerlink" title="链式操作"></a>链式操作</h3><p>思想：最终选中网页元素以后，可以对它进行一系列操作，并且所有操作可以连接在一起，以链条的形式写出来</p>
<p>这样以点连起来的连续调用就称为链式调用，它的设计原理是<strong>把jQuery中的函数返回为这个对象，然后这个对象又包含jQuery的所有方法，这样就可以实现链式调用，十分方便</strong>。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">$(<span class="string">&#x27;div&#x27;</span>).<span class="title function_">find</span>(<span class="string">&#x27;h3&#x27;</span>).<span class="title function_">eq</span>(<span class="number">2</span>).<span class="title function_">html</span>(<span class="string">&#x27;Hello&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//分解开，可以这么理解</span></span><br><span class="line">$(<span class="string">&#x27;div&#x27;</span>) <span class="comment">//找到div元素</span></span><br><span class="line">　　　.<span class="title function_">find</span>(<span class="string">&#x27;h3&#x27;</span>) <span class="comment">//选择其中的h3元素</span></span><br><span class="line">　　　.<span class="title function_">eq</span>(<span class="number">2</span>) <span class="comment">//选择第3个h3元素</span></span><br><span class="line">　　　.<span class="title function_">html</span>(<span class="string">&#x27;Hello&#x27;</span>); <span class="comment">//将它的内容改为Hello</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//jQuery还提供了.end()方法，使得结果可以后退一步</span></span><br><span class="line">$(<span class="string">&#x27;div&#x27;</span>)</span><br><span class="line">　　　.<span class="title function_">find</span>(<span class="string">&#x27;h3&#x27;</span>)</span><br><span class="line">　　　.<span class="title function_">eq</span>(<span class="number">2</span>)</span><br><span class="line">　　　.<span class="title function_">html</span>(<span class="string">&#x27;Hello&#x27;</span>)</span><br><span class="line">　　　.<span class="title function_">end</span>() <span class="comment">//退回到选中所有的h3元素的那一步</span></span><br><span class="line">　　　.<span class="title function_">eq</span>(<span class="number">0</span>) <span class="comment">//选中第一个h3元素</span></span><br><span class="line">　　　.<span class="title function_">html</span>(<span class="string">&#x27;World&#x27;</span>); <span class="comment">//将它的内容改为World</span></span><br></pre></td></tr></table></figure>



<h3 id="移动元素"><a href="#移动元素" class="headerlink" title="移动元素"></a>移动元素</h3><p>思想：jQuery提供两组方法，来操作元素在网页中的位置移动。一组方法是直接移动该元素，另一组方法是移动其他元素，使得目标元素达到我们想要的位置</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//第一种方法是使用.insertAfter()</span></span><br><span class="line"><span class="comment">//把div元素移动p元素后面</span></span><br><span class="line">$(<span class="string">&#x27;div&#x27;</span>).<span class="title function_">insertAfter</span>($(<span class="string">&#x27;p&#x27;</span>));</span><br><span class="line"></span><br><span class="line"><span class="comment">//第二种方法是使用.after()</span></span><br><span class="line"><span class="comment">//把p元素加到div元素前面</span></span><br><span class="line">$(<span class="string">&#x27;p&#x27;</span>).<span class="title function_">after</span>($(<span class="string">&#x27;div&#x27;</span>));</span><br></pre></td></tr></table></figure>

<blockquote>
<p>二者区别：返回的元素不一样。第一种方法返回div元素，第二种方法返回p元素。</p>
</blockquote>
<p>类似操作方法共4对</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">　.<span class="title function_">insertAfter</span>()和.<span class="title function_">after</span>() <span class="comment">//在现存元素的外部，从后面插入元素</span></span><br><span class="line">　.<span class="title function_">insertBefore</span>()和.<span class="title function_">before</span>() <span class="comment">//在现存元素的外部，从前面插入元素</span></span><br><span class="line">　.<span class="title function_">appendTo</span>()和.<span class="title function_">append</span>() <span class="comment">//在现存元素的内部，从后面插入元素</span></span><br><span class="line">　.<span class="title function_">prependTo</span>()和.<span class="title function_">prepend</span>() <span class="comment">//在现存元素的内部，从前面插入元素</span></span><br></pre></td></tr></table></figure>



<h3 id="重载"><a href="#重载" class="headerlink" title="重载"></a>重载</h3><p>jQuery中，构造函数$()<strong>支持多种参数</strong></p>
<ul>
<li>.attr(name，value)和.attr(name)：两个参数是设置属性，一个参数是获取属性值</li>
<li>.text()和.text(string)：无参数是获取文本，一个参数是写入文本</li>
<li>.html()和.html(string)：无参数是获取html元素，一个参数是写入html元素</li>
</ul>
<p>结合下面这段代码，参数可以是选择器、数组或一段代码</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">window</span>.<span class="property">jQuery</span> = <span class="keyword">function</span>(<span class="params">selectorOrArrayOrTemplate</span>)&#123;</span><br><span class="line">  <span class="keyword">let</span> elements</span><br><span class="line">  <span class="keyword">if</span>(<span class="keyword">typeof</span> selectorOrArrayOrTemplate === <span class="string">&#x27;string&#x27;</span>)&#123;</span><br><span class="line">    <span class="keyword">if</span>(selectorOrArrayOrTemplate[<span class="number">0</span>] === <span class="string">&#x27;&lt;&#x27;</span>)&#123;</span><br><span class="line">      <span class="comment">// 创建 div</span></span><br><span class="line">      elements=[<span class="title function_">createElement</span>(selectorOrArrayOrTemplate)]</span><br><span class="line">    &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">      <span class="comment">// 查找 div</span></span><br><span class="line">      elements = <span class="variable language_">document</span>.<span class="title function_">querySelectorAll</span>(selectorOrArrayOrTemplate)</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;<span class="keyword">else</span> <span class="keyword">if</span>(selectorOrArrayOrTemplate <span class="keyword">instanceof</span> <span class="title class_">Array</span>)&#123;</span><br><span class="line">    elements = selectorOrArrayOrTemplate</span><br><span class="line">  &#125;</span><br><span class="line">  </span><br><span class="line">  <span class="comment">//举例</span></span><br><span class="line">  $(<span class="string">&#x27;div&#x27;</span>)</span><br><span class="line">  $(<span class="string">&#x27;&lt;div&gt;hello&lt;/div&gt;&#x27;</span>)</span><br><span class="line">    </span><br><span class="line">    </span><br></pre></td></tr></table></figure>



<h3 id="getter-setter"><a href="#getter-setter" class="headerlink" title="getter/setter"></a>getter/setter</h3><p>思想：使用同一个函数，来完成取值（getter）和赋值（setter），到底是取值还是赋值，由函数的参数决定。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$(<span class="string">&#x27;h1&#x27;</span>).<span class="title function_">html</span>(); <span class="comment">//html()没有参数，表示取出h1的值</span></span><br><span class="line">$(<span class="string">&#x27;h1&#x27;</span>).<span class="title function_">html</span>(<span class="string">&#x27;Hello&#x27;</span>); <span class="comment">//html()有参数Hello，表示对h1进行赋值</span></span><br></pre></td></tr></table></figure>

<p>常见的取值和赋值函数</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">.<span class="title function_">html</span>() 取出或设置html内容</span><br><span class="line">.<span class="title function_">text</span>() 取出或设置text内容</span><br><span class="line">.<span class="title function_">attr</span>() 取出或设置某个属性的值</span><br><span class="line">.<span class="title function_">width</span>() 取出或设置某个元素的宽度</span><br><span class="line">.<span class="title function_">height</span>() 取出或设置某个元素的高度</span><br><span class="line">.<span class="title function_">val</span>() 取出某个表单元素的值</span><br></pre></td></tr></table></figure>

<blockquote>
<p>如果结果集包含多个元素，那么赋值的时候，将对其中所有的元素赋值。<br>取值的时候，则是只取出第一个元素的值（.text()例外，它取出所有元素的text内容）</p>
</blockquote>
<h3 id="适配器"><a href="#适配器" class="headerlink" title="适配器"></a>适配器</h3><p>jQuery针对不同浏览器使用不同代码，也就是兼容各个浏览器。</p>
<h3 id="用闭包隐藏细节"><a href="#用闭包隐藏细节" class="headerlink" title="用闭包隐藏细节"></a>用闭包隐藏细节</h3><p>思想：浏览器必须通过内部的函数来操作外部参数，如用get()或find()来操作elements，可以隐藏细节。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">window</span>.<span class="property">$</span> = <span class="variable language_">window</span>.<span class="property">jQuery</span> = <span class="keyword">function</span>(<span class="params">selectorOrArrayOrTemplate</span>) &#123;</span><br><span class="line">  <span class="keyword">let</span> elements;</span><br><span class="line">  <span class="keyword">if</span> (<span class="keyword">typeof</span> selectorOrArrayOrTemplate === <span class="string">&quot;string&quot;</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (selectorOrArrayOrTemplate[<span class="number">0</span>] === <span class="string">&quot;&lt;&quot;</span>) &#123;</span><br><span class="line">      <span class="comment">// 创建 div</span></span><br><span class="line">      elements = [<span class="title function_">createElement</span>(selectorOrArrayOrTemplate)];</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="comment">// 查找 div</span></span><br><span class="line">      elements = <span class="variable language_">document</span>.<span class="title function_">querySelectorAll</span>(selectorOrArrayOrTemplate);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125; <span class="keyword">else</span> <span class="keyword">if</span> (selectorOrArrayOrTemplate <span class="keyword">instanceof</span> <span class="title class_">Array</span>) &#123;</span><br><span class="line">    elements = selectorOrArrayOrTemplate;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">function</span> <span class="title function_">createElement</span>(<span class="params">string</span>) &#123;</span><br><span class="line">    <span class="keyword">const</span> container = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&quot;template&quot;</span>);</span><br><span class="line">    container.<span class="property">innerHTML</span> = string.<span class="title function_">trim</span>();</span><br><span class="line">    <span class="keyword">return</span> container.<span class="property">content</span>.<span class="property">firstChild</span>;</span><br><span class="line">  &#125;</span><br><span class="line">  </span><br><span class="line">  jQuery.<span class="property">fn</span> = jQuery.<span class="property"><span class="keyword">prototype</span></span> = &#123;</span><br><span class="line">    <span class="attr">constructor</span>: jQuery,</span><br><span class="line">    <span class="title function_">get</span>(<span class="params">index</span>) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">elements</span>[index];</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="title function_">find</span>(<span class="params">selector</span>) &#123;</span><br><span class="line">      <span class="keyword">let</span> array = [];</span><br><span class="line">      <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; <span class="variable language_">this</span>.<span class="property">elements</span>.<span class="property">length</span>; i++) &#123;</span><br><span class="line">        <span class="keyword">const</span> elements2 = <span class="title class_">Array</span>.<span class="title function_">from</span>(<span class="variable language_">this</span>.<span class="property">elements</span>[i].<span class="title function_">querySelectorAll</span>(selector));</span><br><span class="line">        array = array.<span class="title function_">concat</span>(<span class="variable language_">this</span>.<span class="property">elements2</span>);</span><br><span class="line">      &#125;</span><br><span class="line">      array.<span class="property">oldApi</span> = <span class="variable language_">this</span>; <span class="comment">// this 就是 旧 api</span></span><br><span class="line">      <span class="keyword">return</span> <span class="title function_">jQuery</span>(array);</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>参考自：</p>
<p><a target="_blank" rel="noopener" href="http://www.ruanyifeng.com/blog/2011/07/jquery_fundamentals.html">jQuery设计思想</a></p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/09/12/56/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/lion.jpg">
      <meta itemprop="name" content="Xiaolong">
      <meta itemprop="description" content="Never stop learning">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Xiaolong's Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/09/12/56/" class="post-title-link" itemprop="url">JS函数</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Posted on</span>

      <time title="Created: 2021-09-12 12:30:56" itemprop="dateCreated datePublished" datetime="2021-09-12T12:30:56+08:00">2021-09-12</time>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h2 id="定义函数"><a href="#定义函数" class="headerlink" title="定义函数"></a>定义函数</h2><p>定义一个函数</p>
<ul>
<li><p>具名函数</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> 函数名(形式参数<span class="number">1</span>, 形式参数<span class="number">2</span>)&#123;</span><br><span class="line">    <span class="keyword">return</span> 返回值</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li><p>匿名函数, 具名函数去掉函数名就是匿名函数</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a = <span class="keyword">function</span>(<span class="params">x, y</span>)&#123;</span><br><span class="line">    <span class="keyword">return</span> x + y</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 也叫函数表达式</span></span><br></pre></td></tr></table></figure></li>
<li><p>箭头函数</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> <span class="title function_">f1</span> = x =&gt; x * x</span><br><span class="line"><span class="keyword">let</span> <span class="title function_">f2</span> = (<span class="params">x, y</span>) =&gt; x + y <span class="comment">// 圆括号不能省</span></span><br><span class="line"><span class="keyword">let</span> <span class="title function_">f3</span> = (<span class="params">x, y</span>) =&gt; &#123; <span class="keyword">return</span> x - y&#125; <span class="comment">// 花括号不能省</span></span><br><span class="line"><span class="keyword">let</span> <span class="title function_">f4</span> = (<span class="params">x, y</span>) =&gt; (&#123;<span class="attr">name</span>: x, <span class="attr">age</span>: y&#125;)</span><br><span class="line"><span class="comment">// 直接返回对象 需要加个圆括号</span></span><br></pre></td></tr></table></figure></li>
<li><p>构造函数</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> f = <span class="keyword">new</span> <span class="title class_">Function</span>(<span class="string">&#x27;x&#x27;</span>, <span class="string">&#x27;y&#x27;</span>, <span class="string">&#x27;return x + y&#x27;</span>)</span><br><span class="line"><span class="comment">// 基本没人用, 但是能让你知道函数是谁构造的</span></span><br><span class="line"><span class="comment">// 所有函数都是 Function 构造的</span></span><br><span class="line"><span class="comment">// 包括 Object、Array、Function</span></span><br></pre></td></tr></table></figure></li>
</ul>
<h2 id="函数的要素"><a href="#函数的要素" class="headerlink" title="函数的要素"></a>函数的要素</h2><p>每个函数都拥有这些</p>
<ul>
<li>调用时机</li>
<li>作用域</li>
<li>闭包</li>
<li>形式参数</li>
<li>返回值</li>
<li>调用栈</li>
<li>函数提升</li>
<li>arguments（除了箭头函数）</li>
<li>this（除了箭头函数）</li>
</ul>
<h3 id="调用时机"><a href="#调用时机" class="headerlink" title="调用时机"></a>调用时机</h3><p>时机不同, 结果不同</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a = <span class="number">1</span>;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">fn</span>(<span class="params"></span>)&#123;</span><br><span class="line">    <span class="built_in">setTimeout</span>( <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(a)</span><br><span class="line">    &#125;, <span class="number">0</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="title function_">fn</span>()</span><br><span class="line">a = <span class="number">2</span></span><br><span class="line"><span class="comment">// 打印结果为 2</span></span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> i = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">for</span>(i = <span class="number">0</span>; i &lt; <span class="number">6</span>; i++)&#123;</span><br><span class="line">    <span class="title function_">setTimeoug</span>( <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(i)</span><br><span class="line">    &#125;, <span class="number">0</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 打印结果为 6个6</span></span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>(<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; <span class="number">6</span>; i++)&#123;</span><br><span class="line">    <span class="title function_">setTimeoug</span>( <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(i)</span><br><span class="line">    &#125;, <span class="number">0</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 打印结果为 0, 1, 2, 3, 4, 5</span></span><br><span class="line"><span class="comment">// 因为 JS　在　for 和 let 一起用的时候会加东西</span></span><br><span class="line"><span class="comment">// 每次循环会多创建一个 i</span></span><br></pre></td></tr></table></figure>



<h3 id="作用域"><a href="#作用域" class="headerlink" title="作用域"></a>作用域</h3><p>每个函数都会创建一个作用域</p>
<p><a target="_blank" rel="noopener" href="https://blog.fundebug.com/2019/03/15/understand-javascript-scope/">深入理解 JS 作用域和作用域链</a></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 例1</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">fn</span>(<span class="params"></span>)&#123; <span class="keyword">let</span> a = <span class="number">1</span>; &#125;</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(a) <span class="comment">// a 不存在</span></span><br><span class="line"><span class="comment">// 问: 是不是因为 fn 没执行导致</span></span><br><span class="line"><span class="comment">// 答: 就算 fn 执行了,也访问不到作用域里面的 a</span></span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 例2function f1()&#123;    let a = 1;        function f2()&#123;        let a = 2;         console.log(a);    &#125;        console.log(a);    a = 3;    f2();    console.log(a)&#125;f1()// 打印结果为 /*  1 	2	3*/</span></span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 例3function f1()&#123;    let a = 1;    function f2()&#123;        let a = 2;        function f3()&#123;            console.log(a)        &#125;        a = 22;        f3();    &#125;    console.log(a);    a = 100;    f2();&#125;f1();/* 打印机结果为122*/</span></span><br></pre></td></tr></table></figure>

<blockquote>
<p><strong>如果多个作用域有同名变量 a</strong></p>
<p>那么查找 a 的声明式, 就向上取最近的作用域, 简称[就近原则]</p>
<p>查找 a 的过程与函数执行无关</p>
<p>但 a 的值与函数执行有关</p>
</blockquote>
<h3 id="闭包"><a href="#闭包" class="headerlink" title="闭包"></a>闭包</h3><p><a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/22486908">JS中的闭包是什么</a></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">f1</span>(<span class="params"></span>)&#123;    <span class="keyword">let</span> a = <span class="number">1</span>;    <span class="keyword">function</span> <span class="title function_">f2</span>(<span class="params"></span>)&#123;        <span class="comment">//        let a = 2;        function f3()&#123;            console.log(a)        &#125;//               /*		如果一个函数用到外部的变量		那么这个函数加这个变量		就叫做 闭包		左边的 a 和 f3 组成了 闭包		*/                a = 22;        f3();    &#125;    console.log(a);    a = 100;    f2();&#125;f1();</span></span><br></pre></td></tr></table></figure>



<h3 id="形式参数"><a href="#形式参数" class="headerlink" title="形式参数"></a>形式参数</h3><p>形式参数意思式非实际参数</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">add</span> (x, y)&#123;    <span class="keyword">return</span> x + y;&#125;<span class="comment">// 其中 x 和 y 就是形参,因为并不是时机的参数add(1, 2);// 调用 add 时,1 和 2 是实际参数,会被复制给 x y// 上面代码近似等于下面代码function add()&#123;    var x = arguments[0]    var y = arguments[1]    return x + y&#125;</span></span><br></pre></td></tr></table></figure>



<h3 id="返回值"><a href="#返回值" class="headerlink" title="返回值"></a>返回值</h3><p>每个函数都有返回值</p>
<p>函数执行完了后才会返回</p>
<p>只有函数有返回值</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">hi</span>(<span class="params"></span>) &#123; <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;hi&#x27;</span>); &#125;<span class="title function_">hi</span>();<span class="comment">// 没写 return, 所以返回值是 undefinedfunction hi() &#123; return console.log(&#x27;hi&#x27;); &#125;hi()// 返回值为 console.log(&#x27;hi&#x27;) 的值,即 undefined</span></span><br></pre></td></tr></table></figure>



<h3 id="调用栈"><a href="#调用栈" class="headerlink" title="调用栈"></a>调用栈</h3><p>什么是调用栈</p>
<blockquote>
<p>JS 引擎在调用一个函数前</p>
<p>需要把函数所在的环境 push 到一个数组里</p>
<p>这个数组叫做调用栈</p>
<p>等函数执行完了, 就会把环境弹 (pop) 出来</p>
<p>然后 return 到之前的环境, 继续执行后续代码</p>
</blockquote>
<center><img src="https://cdn.jsdelivr.net/gh/Drwna/image//images/Snipaste_2021-09-02_17-04-35.png" alt="Snipaste_2021-09-02_17-04-35"></center><center style="font-size:14px;color:#C0C0C0;text-decoration:underline">调用栈 图示</center> 



<p>爆栈, 如果调用栈中压入的帧过多, 程序就会奔溃</p>
<p>递归函数</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 阶乘function f(n) &#123;    return n !== 1 ? n * f(n - 1) : 1&#125;// 理解递归f(4)= 4 * f(3)= 4 * (3 * f(2))= 4 * (3 * (2 * f(1)))= 4 * (3 * (1))= 4 * (6)= 24// 先递进, 后回归</span></span><br></pre></td></tr></table></figure>

<center><img src="https://cdn.jsdelivr.net/gh/Drwna/image//images/Snipaste_2021-09-02_17-36-31.png" alt="Snipaste_2021-09-02_17-36-31" width='800px'></center><center style="font-size:14px;color:#C0C0C0;text-decoration:underline">递归函数调用栈 图示</center> 



<p>调用栈最长有多少</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 测试调用栈长度function computeMaxCallStackSize() &#123;    try &#123;        return 1 + computeMaxCallStackSize();    &#125; catch(e) &#123;        // 报错说明 stack overflow 了        return 1    &#125;&#125;/*chrom 11409firefox 24740node 12536*/</span></span><br></pre></td></tr></table></figure>



<h3 id="函数提升"><a href="#函数提升" class="headerlink" title="函数提升"></a>函数提升</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">fn</span>(<span class="params"></span>)&#123;&#125;<span class="comment">// 不管把具名函数声明在哪里, 它都会跑到第一行</span></span><br></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://www.cnblogs.com/liuhe688/p/5891273.html">JS 变量提升和函数提升</a></p>
<p><a target="_blank" rel="noopener" href="https://segmentfault.com/a/1190000038344251">前端面试必考-JS 变量提升和函数提升详解</a></p>
<h3 id="arguments-和-this"><a href="#arguments-和-this" class="headerlink" title="arguments 和 this"></a>arguments 和 this</h3><p>每个函数都有 arguments 和 this ，除了箭头函数</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">fn</span>(<span class="params"></span>)&#123;    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">arguments</span>);    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>)&#125;<span class="title function_">fn</span>()<span class="comment">// arguments 是包含所有参数的 伪数组// 如果不给任何条件 this 默认指向 window</span></span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">fn</span>(<span class="params"></span>)&#123;    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>)&#125;<span class="title function_">fn</span>()fn.<span class="title function_">call</span>(<span class="number">1</span>) <span class="comment">// 打印出的 数字 1 被自动转化成对象 1function fn()&#123;    &#x27;use strict&#x27;    console.log(this)&#125;fn.call(1) // 打印出 数字 1function fn()&#123;  console.log(this);  console.log(arguments)&#125;// 传入的第一个参数是 this, 其余的是 argumentsfn.call(1, 2, 4)/*打印结果Number (1)Arguments&#123;0: 2, 1: 4 ...&#125;*/</span></span><br></pre></td></tr></table></figure>

<center><img src="https://cdn.jsdelivr.net/gh/Drwna/image//images/Snipaste_2021-09-02_21-14-03.png" alt="Snipaste_2021-09-02_21-14-03" width="600px"></center><center style="font-size:14px;color:#C0C0C0;text-decoration:underline">arguments 和 this</center> 

<blockquote>
<p>this 是隐藏参数</p>
<p>arguments 是普通参数</p>
<p>this 是参数(个人结论)</p>
</blockquote>
<h4 id="假如没有-this"><a href="#假如没有-this" class="headerlink" title="假如没有 this"></a>假如没有 this</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> person = &#123;    <span class="attr">name</span>: <span class="string">&#x27;frank&#x27;</span>,    <span class="title function_">sayHi</span>(<span class="params"></span>)&#123;        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;hello, i am &#x27;</span> + person.<span class="property">name</span>);    &#125;&#125;person.<span class="title function_">sayHi</span>()<span class="comment">/* 分析可以用直接保存了对象地址的 变量 获取 &#x27;name&#x27;这种办法简称为 引用*/</span></span><br></pre></td></tr></table></figure>

<h4 id="问题一"><a href="#问题一" class="headerlink" title="问题一"></a>问题一</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> sayHi = <span class="keyword">function</span>(<span class="params"></span>)&#123;    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;hello, i am &#x27;</span> + <span class="comment">/* person*/</span>.<span class="property">name</span>)&#125;<span class="keyword">let</span> person = &#123;    <span class="attr">name</span>: <span class="string">&#x27;frank&#x27;</span>,    <span class="string">&#x27;sayHi&#x27;</span>: sayHi.&#125;<span class="comment">/*分析person 如果改名，sayHi 函数就挂了sayHi 函数甚至有可能在另一个文件里所以我们不希望 sayHi 函数里出现 person 引用*/</span></span><br></pre></td></tr></table></figure>

<h4 id="问题二"><a href="#问题二" class="headerlink" title="问题二"></a>问题二</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Perosn</span> &#123;    <span class="title function_">constructot</span>(<span class="params">name</span>)&#123;        <span class="variable language_">this</span>.<span class="property">name</span> = name        <span class="comment">// 这里的 this 是 new 强制指定的    &#125;    sayHi()&#123;        console.log(/*????*/)    &#125;&#125;/*分析这里只有类，还没创建对象，故不可能获取对象的引用那么如何拿到对象的 name ？*//*需要一种办法拿到对象这样才能获取对象的 name 属性*/</span></span><br></pre></td></tr></table></figure>

<h4 id="一种土方法，用参数"><a href="#一种土方法，用参数" class="headerlink" title="一种土方法，用参数"></a>一种土方法，用参数</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 对象let person = &#123;    name: &#x27;frank&#x27;,    sayHi(p) &#123;        console.log(&#x27;hello, i am &#x27; + p.name)    &#125;&#125;person.sayHi(person)// 类class Person &#123;    constructor(name)&#123; this.name = name &#125;    sayHi(p) &#123;        console.log(&#x27;hello, i am &#x27; + p.name)    &#125;&#125;let person = new Person(&#x27;frank&#x27;)person.sayHi(person)</span></span><br></pre></td></tr></table></figure>

<h4 id="JS-在每个函数里加了-this"><a href="#JS-在每个函数里加了-this" class="headerlink" title="JS 在每个函数里加了 this"></a>JS 在每个函数里加了 this</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 用 this 获取那个对象let person = &#123;    name: &#x27;frank&#x27;,    sayHi(/*this*/)&#123;        console.log(&#x27;hello, i am &#x27; + this.name)    &#125;&#125;person.sayHi()/*person.sahHi()相当于 person.sayHi(person)然后 person 被传给 this 了 (person 是个地址)这样每个函数都能用 this 获取一个未知对象的引用了*/// person.sayHi() 会隐式地把 person 作为 this 传给 sayHi// 方便 sayHi 获取 person 对应的对象</span></span><br></pre></td></tr></table></figure>

<h4 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h4><blockquote>
<p>我们想让函数获取对象的引用</p>
<p>但是并不想通过变量名做到</p>
<p>Python 通过额外的 self 参数做到 </p>
<p>JS 通过额外的 this 做到:</p>
<p>person.sayHi() 会把person 自动传给 sayHi, sayHi 可以通过 this 引用 person</p>
</blockquote>
<p>其他</p>
<ul>
<li>注意 person.sayHi 和 person.sayHi() 的区别</li>
<li>注意 person.sayHi() 的短句 (person.sayHi)()</li>
</ul>
<h4 id="call-指定-this"><a href="#call-指定-this" class="headerlink" title="call 指定 this"></a>call 指定 this</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 哪个对let person = &#123;    name: &#x27;frank&#x27;,    sayHi(/*this*/)&#123;        console.log(&#x27;hello, i am &#x27; + this.name)    &#125;&#125;person.sayHi()Person.sayHi(person)// 省略形式的反而是对的// 两种调用方式person.sayHi()// 会自动把 person 传到函数里, 作为 thisperson.sayHi.call(person)person.sayHi.call(&#123;name: &#x27;evan&#x27;&#125;)// 需要手 动把 person 传到函数里,作为 this// 推荐使用</span></span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 例1function add(x, y) &#123;    return x + y&#125;add.call(undefined, 1, 2) // 3/*为什么要多写一个 undefined因为第一个参数要作为 this但是代码里没有用 this所以只能用 undefined 占位其实用 null 也可以*/</span></span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 例2Array.prototype.forEach2 = function(fn)&#123;    for(let i = 0; i &lt; this.length; i++)&#123;        fn(this[i], i, this)    &#125;&#125;let arr1 = [2, 4, 5]// 两种调用方式arr1.forEach2.call(arr1, (item) = &gt; console.log(item))arr1.forEach2((item) = &gt; console.log(item))/* this 是什么由于大家使用 forEach2 的时候总是会用 arr.forEach2所以 arr1 就被自动传给 foreEach2 了*//* this 一定是数组吗不一定, 比如Array.prototype.forEach2.call(&#123;0: &#x27;a&#x27;, 1: &#x27;b&#x27;,length: 2&#125;)*/</span></span><br></pre></td></tr></table></figure>

<p><strong>this 的两种使用方法</strong></p>
<ul>
<li><p>隐式传递</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">fn</span>(<span class="number">1</span>, <span class="number">2</span>) <span class="comment">// 等价于 fn.call(undefined, 1, 2)obj.child.fn(1) // 等价于 obj.child.fn.call(obj.child, 1)</span></span><br></pre></td></tr></table></figure></li>
<li><p>显示传递</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">fn.<span class="title function_">call</span>(<span class="literal">undefined</span>, <span class="number">1</span>, <span class="number">2</span>)fn.<span class="title function_">apply</span>(<span class="literal">undefined</span>, [<span class="number">1</span>, <span class="number">2</span>]) <span class="comment">// 数组</span></span><br></pre></td></tr></table></figure></li>
</ul>
<p>**绑定 this **</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 使用 .bind 可以让 this 不被改变function f1(p1, p2)&#123;    console.log(this, p1, p2)&#125;let f2 = f1.bind(&#123;name: &#x27;frank&#x27;&#125;)// 那么 f2 就是 f1 绑定 this 之后的新函数f2() // 等价于 f1.call(&#123;name: &#x27;frank&#x27;&#125;)</span></span><br></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://segmentfault.com/a/1190000004580525">快速理解 JS 中 this 的用法与陷阱</a></p>
<h2 id="箭头函数"><a href="#箭头函数" class="headerlink" title="箭头函数"></a>箭头函数</h2><p><strong>没有 arguments 和 this</strong></p>
<p>里面的 this 就是外面的 this</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="variable language_">this</span>) <span class="comment">// windowlet fn = () =&gt; console.log(this)fn() // window// 就算加了 call 也没用fn.call(&#123;name: &#x27;frank&#x27;&#125;) // window</span></span><br></pre></td></tr></table></figure>



<h2 id="立即执行函数"><a href="#立即执行函数" class="headerlink" title="立即执行函数"></a>立即执行函数</h2><center><img src="https://cdn.jsdelivr.net/gh/Drwna/image//images/Snipaste_2021-09-03_23-05-46.png" alt="Snipaste_2021-09-03_23-05-46" width="800px"></center><center style="font-size:14px;color:#C0C0C0;text-decoration:underline">立即执行函数</center> 

<p>推荐 <a target="_blank" rel="noopener" href="https://segmentfault.com/a/1190000003902899">JS 中的立即执行函数</a></p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/09/08/14/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/lion.jpg">
      <meta itemprop="name" content="Xiaolong">
      <meta itemprop="description" content="Never stop learning">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Xiaolong's Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/09/08/14/" class="post-title-link" itemprop="url">跨域</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Posted on</span>

      <time title="Created: 2021-09-08 12:26:14" itemprop="dateCreated datePublished" datetime="2021-09-08T12:26:14+08:00">2021-09-08</time>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <p>跨域关键知识：</p>
<ul>
<li>同源策略。浏览器故意设计的一个功能限制</li>
<li>CORS。突破浏览器限制的一个方法</li>
<li>JSONP。IE 时代的妥协</li>
</ul>
<h2 id="同源"><a href="#同源" class="headerlink" title="同源"></a>同源</h2><p>源 = 协议 + 域名 + 端口号</p>
<p><code>window.origin</code> 或 <code>location.origin</code> 可以得到当前源。</p>
<p>如果两个 url 的<strong>协议、域名、端口号完全一致</strong>，那么这两个 url 就是同源。</p>
<p>例：<code>https://qq.com</code> 和 <code>https://www.baidu.com</code>     不同源</p>
<p><code>https://baidu.com</code> 和 <code>https:www.baidu.com</code>     同源</p>
<p>完全一致才算同源</p>
<p>下表给出了与 URL <code>http://store.company.com/dir/page.html</code> 的源进行对比的示例:</p>
<table>
<thead>
<tr>
<th align="left">URL</th>
<th align="left">结果</th>
<th align="left">原因</th>
</tr>
</thead>
<tbody><tr>
<td align="left"><code>http://store.company.com/dir2/other.html</code></td>
<td align="left">同源</td>
<td align="left">只有路径不同</td>
</tr>
<tr>
<td align="left"><code>http://store.company.com/dir/inner/another.html</code></td>
<td align="left">同源</td>
<td align="left">只有路径不同</td>
</tr>
<tr>
<td align="left"><code>https://store.company.com/secure.html</code></td>
<td align="left">失败</td>
<td align="left">协议不同</td>
</tr>
<tr>
<td align="left"><code>http://store.company.com:81/dir/etc.html</code></td>
<td align="left">失败</td>
<td align="left">端口不同 ( <code>http://</code> 默认端口是80)</td>
</tr>
<tr>
<td align="left"><code>http://news.company.com/dir/other.html</code></td>
<td align="left">失败</td>
<td align="left">主机不同</td>
</tr>
</tbody></table>
<h2 id="同源策略"><a href="#同源策略" class="headerlink" title="同源策略"></a>同源策略</h2><p>Ajax 最大的限制是同源策略（Same-origin policy），它限制了不同源之间的交互，一个源的文档或脚本不能与另一个源的资源进行交互。<a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/Security/Same-origin_policy">浏览器的同源策略 MDN</a></p>
<ul>
<li><p>浏览器规定</p>
<p>如果 JS 运行在源 A 里，那么就只能获取源 A 的数据</p>
<p>不能获取源 B 的数据，即==不允许跨域==</p>
</li>
<li><p>例如（省略 http 协议）</p>
<p>假设 frank.com/index.html 引用了 cdn.com/1.js</p>
<p>那么就说 1.js 运行在源 frank.com 里</p>
<p>注意 这跟 cdn.com 没有关系，虽然 1.js 从它哪下载</p>
<p>所以 1.js 就只能获取 frank.com 的数据</p>
<p>不能获取 1.frank.com 或者 qq.com 的数据</p>
</li>
<li><p>这是浏览器的功能</p>
<p>浏览器故意要这样设计的</p>
<p>目的：==保护用户隐私==</p>
</li>
</ul>
<h2 id="如果没有同源策略"><a href="#如果没有同源策略" class="headerlink" title="如果没有同源策略"></a>如果没有同源策略</h2><p>以 qq 空间为例</p>
<p>源为 <code>https://user.qzone.qq.com</code>，假设，当前用户已登录（cookie），假设 AJAX 请求 /friends.json 可获取到用户好友列表。</p>
<p>黑客来了，假设有人给你分享 <code>https://qzone-qq.com </code> 给你，实际上是个钓鱼网站，你点开后，这个网页会请求你的好友列表 <code>https://user.qzone.qq.com/friends.json</code>。这样好友列表就能被黑客访问到。</p>
<p><strong>问题根源：</strong></p>
<ul>
<li><p>无法区分发送者</p>
<p>qq 空间页面的 JS 和黑客网页里的 JS 发送的请求几乎没有区别（referrer 有区别）</p>
<p>如果后台开发者没有检查 referrer，那么就完全没有区别</p>
<p>所以，没有同源策略，任何页面都能偷 qq 空间的数据</p>
</li>
<li><p>那检查 referrer 不就好了</p>
<p>安全原则：安全链条的强度取决于最弱的一环</p>
<p>万一这个网站的后端开发工程师就是没有检查 referrer</p>
<p>所以浏览器应该主动预防这种偷数据的行为</p>
<p>总之，浏览器为了用户隐私，设置了严格的同源策略</p>
</li>
</ul>
<h2 id="演示"><a href="#演示" class="headerlink" title="演示"></a>演示</h2><ol>
<li><p>创建目录</p>
<p>qq-com 里新建 server.js，用来模拟 qq空间</p>
<p>frank-com 里新建 server.js，用来模拟黑客网站</p>
</li>
<li><p>qq-com</p>
<p>public 目录下新建 index.html 首页</p>
<p>qq.js 是 JS 脚本文件</p>
<p>friends.json 是模拟的好友数据</p>
<p>端口监听为 8888，访问 <code>http://127.0.0.1:8888</code></p>
</li>
<li><p>hacker-com</p>
<p>public 目录下新建 index.html 首页</p>
<p>frank.js 是 JS 脚本文件</p>
<p>端口监听为 9999，范问 <code>http://127.0.0.1:9999</code></p>
</li>
</ol>
<p>跨域 AJAX</p>
<ul>
<li><p>正常使用 AJAX</p>
<p>在 qq.com:8888 里运行的 JS 可以访问 /friends.json</p>
<center><img src="https://cdn.jsdelivr.net/gh/Drwna/image//images/Snipaste_2021-09-27_01-44-31.png" alt="Snipaste_2021-09-27_01-44-31" width="800px"></center><center style="font-size:14px;color:#C0C0C0;text-decoration:underline">能够访问</center> </li>
<li><p>黑客偷数据</p>
<p>在 hacker.com:9999 里运行的 JS不能访问</p>
<p>浏览器需要==CORS==</p>
</li>
</ul>
<center><img src="https://cdn.jsdelivr.net/gh/Drwna/image//images/Snipaste_2021-09-27_01-44-56.png" alt="Snipaste_2021-09-27_01-44-56" width="800px"></center><center style="font-size:14px;color:#C0C0C0;text-decoration:underline">不能访问</center> 

<ul>
<li><p>提问</p>
<p>黑客的请求成功了没：</p>
<p>答：成功了，因为 qq.com 后台有 log。</p>
<p>黑客拿到响应了没与？</p>
<p>答：没有，因为浏览器不给数据。</p>
</li>
</ul>
<center><img src="https://cdn.jsdelivr.net/gh/Drwna/image//images/Snipaste_2021-09-27_01-53-35.png" alt="Snipaste_2021-09-27_01-53-35" width="800px"></center>



<h2 id="如何跨域"><a href="#如何跨域" class="headerlink" title="如何跨域"></a>如何跨域</h2><h3 id="CORS"><a href="#CORS" class="headerlink" title="CORS"></a>CORS</h3><p>CORS 是一个 W3C 标准，全称是”跨域资源共享”（Cross-origin resource sharing）。</p>
<ul>
<li><p>问题根源</p>
<p>浏览器默认不同源之间不能互相访问数据</p>
<p>但是 qq.com 和 hacker.com 都是自己的网站，需要互相访问</p>
</li>
<li><p>用 CORS</p>
<p>浏览器说，如果要共享数据，需要提前声明！</p>
<p>qq.com 在响应头里写 hacker.com 可以访问</p>
<p>语法：<code>Access-Control-Allow-Origin: http://hacker.com:9999</code></p>
</li>
<li><p><a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/HTTP/CORS#%E7%AE%80%E5%8D%95%E8%AF%B7%E6%B1%82">MDN 文档</a></p>
</li>
</ul>
<p>CORS 不兼容 ie 6789</p>
<h3 id="JSONP"><a href="#JSONP" class="headerlink" title="JSONP"></a>JSONP</h3><p><strong>什么是 JSONP？</strong></p>
<p>跨域时，由于当前浏览器不支持 CORS 或因为某些条件不支持 CORS，我们必须使用另外一种方式来跨域。</p>
<p>于是，请求一个 JS 文件，这个 JS 文件会执行事先定义好的回调，这个回调里就有我们需要的数据。</p>
<p><strong>优点：</strong></p>
<ul>
<li>支持 IE </li>
</ul>
<p><strong>缺点：</strong></p>
<ul>
<li>由于是 script 标签，获取不到响应状态</li>
<li>不支持 POST</li>
</ul>
<hr>
<p>演示：hacker.com 访问 qq.com</p>
<ul>
<li>qq.com 将数据写到 /friends.js</li>
<li>frank.com 用 script 标签引用 /friends.js</li>
<li>hacker.com 执行 事先定义好的 window.xxx 函数</li>
<li>/friends.js 执行 window.xxx({friend: […]})</li>
<li>然后 hacker.com 就通过 window.xxx 获取到数据了</li>
<li>window.xxx 就是一个回调！！</li>
</ul>
<p>JSONP 的实现原理演示：</p>
<p>hacker-com 里的 hacker.js</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="variable language_">window</span>.<span class="property">xxx</span> = <span class="function">(<span class="params">data</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(data)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> script = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;script&#x27;</span>);</span><br><span class="line">script.<span class="property">src</span> = <span class="string">&#x27;http://qq.com:8888/friends.js&#x27;</span>;</span><br><span class="line"><span class="variable language_">document</span>.<span class="property">body</span>.<span class="title function_">appendChild</span>(script);</span><br></pre></td></tr></table></figure>

<p>qq-com public目录下新建 friends.js 内容为 <code>window.xxx ( &#123;&#123; data &#125;&#125; )</code></p>
<p>qq-com 的 server.js 添加如下路由</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">else</span> <span class="keyword">if</span> (path === <span class="string">&#x27;/friends.js&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (request.<span class="property">headers</span>[<span class="string">&#x27;referer&#x27;</span>].<span class="title function_">indexOf</span>(<span class="string">&#x27;http://hacker.com:9999&#x27;</span>) === <span class="number">0</span>) &#123;</span><br><span class="line">            response.<span class="property">statusCode</span> = <span class="number">200</span></span><br><span class="line">            response.<span class="title function_">setHeader</span>(<span class="string">&#x27;Content-Type&#x27;</span>, <span class="string">&#x27;text/javascript;charset=utf-8&#x27;</span>)</span><br><span class="line">            <span class="keyword">const</span> string = fs.<span class="title function_">readFileSync</span>(<span class="string">&#x27;./public/friends.js&#x27;</span>).<span class="title function_">toString</span>()</span><br><span class="line">            <span class="keyword">const</span> data = fs.<span class="title function_">readFileSync</span>(<span class="string">&#x27;./public/friends.json&#x27;</span>).<span class="title function_">toString</span>()</span><br><span class="line">            response.<span class="title function_">write</span>(string.<span class="title function_">replace</span>(<span class="string">&#x27;&#123;&#123; data &#125;&#125;&#x27;</span>, data))</span><br><span class="line">            response.<span class="title function_">end</span>()</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            response.<span class="property">statusCode</span> = <span class="number">404</span>;</span><br><span class="line">            response.<span class="title function_">end</span>();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"><span class="comment">// 控制台 window.xxx</span></span><br><span class="line"><span class="comment">// hacker 拿到了 friends.js 的数据</span></span><br></pre></td></tr></table></figure>



<p>优化：</p>
<p>window.xxx 能不能改其他名字？</p>
<p>其实名字不重要，只要 hacker.com 定义的函数名和 qq.com/friends.js 执行的函数名是同一个即可。</p>
<p>将名字穿给 /friends.js</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// hacker.js</span></span><br><span class="line"><span class="keyword">const</span> random = <span class="string">`hackerJSONPCallback`</span> + <span class="title class_">Math</span>.<span class="title function_">random</span>();</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(random);</span><br><span class="line"><span class="variable language_">window</span>[random] = <span class="function">(<span class="params">data</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(data)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> script = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;script&#x27;</span>);</span><br><span class="line">script.<span class="property">src</span> = <span class="string">`http://qq.com:8888/friends.js?functionName=<span class="subst">$&#123;random&#125;</span>`</span>;</span><br><span class="line">script.<span class="property">onload</span> = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    script.<span class="title function_">remove</span>();</span><br><span class="line">&#125;</span><br><span class="line"><span class="variable language_">document</span>.<span class="property">body</span>.<span class="title function_">appendChild</span>(script);</span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// server.js</span></span><br><span class="line"> <span class="keyword">else</span> <span class="keyword">if</span> (path === <span class="string">&#x27;/friends.js&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (request.<span class="property">headers</span>[<span class="string">&#x27;referer&#x27;</span>].<span class="title function_">indexOf</span>(<span class="string">&#x27;http://hacker.com:9999&#x27;</span>) === <span class="number">0</span>) &#123;</span><br><span class="line">            response.<span class="property">statusCode</span> = <span class="number">200</span></span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(query.<span class="property">functionName</span>);</span><br><span class="line">            response.<span class="title function_">setHeader</span>(<span class="string">&#x27;Content-Type&#x27;</span>, <span class="string">&#x27;text/javascript;charset=utf-8&#x27;</span>)</span><br><span class="line">            <span class="keyword">const</span> string = fs.<span class="title function_">readFileSync</span>(<span class="string">&#x27;./public/friends.js&#x27;</span>).<span class="title function_">toString</span>()</span><br><span class="line">            <span class="keyword">const</span> data = fs.<span class="title function_">readFileSync</span>(<span class="string">&#x27;./public/friends.json&#x27;</span>).<span class="title function_">toString</span>()</span><br><span class="line">            response.<span class="title function_">write</span>(string.<span class="title function_">replace</span>(<span class="string">&#x27;&#123;&#123; data &#125;&#125;&#x27;</span>, data).<span class="title function_">replace</span>(<span class="string">`&#123;&#123; xxx &#125;&#125;`</span>, query.<span class="property">functionName</span>))</span><br><span class="line">            response.<span class="title function_">end</span>()</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            response.<span class="property">statusCode</span> = <span class="number">404</span>;</span><br><span class="line">            response.<span class="title function_">end</span>();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// friends.js</span></span><br><span class="line"><span class="variable language_">window</span>[<span class="string">`&#123;&#123; xxx &#125;&#125;`</span>]( &#123;&#123; data &#125;&#125; )</span><br></pre></td></tr></table></figure>



<p>进一步优化</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// hacker.js</span></span><br><span class="line"><span class="comment">// 封装 JSONP</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">jsonp</span>(<span class="params">url</span>) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">const</span> random = <span class="string">`hackerJSONPCallback`</span> + <span class="title class_">Math</span>.<span class="title function_">random</span>();</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(random);</span><br><span class="line">        <span class="variable language_">window</span>[random] = <span class="function">(<span class="params">data</span>) =&gt;</span> &#123;</span><br><span class="line">            <span class="title function_">resolve</span>(data)</span><br><span class="line">        &#125;;</span><br><span class="line">        <span class="keyword">const</span> script = <span class="variable language_">document</span>.<span class="title function_">createElement</span>(<span class="string">&#x27;script&#x27;</span>);</span><br><span class="line">        script.<span class="property">src</span> = <span class="string">`<span class="subst">$&#123;url&#125;</span>?callback=<span class="subst">$&#123;random&#125;</span>`</span>;</span><br><span class="line">        script.<span class="property">onload</span> = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">            script.<span class="title function_">remove</span>();</span><br><span class="line">        &#125;;</span><br><span class="line">        script.<span class="property">onerror</span> = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="title function_">reject</span>();</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="variable language_">document</span>.<span class="property">body</span>.<span class="title function_">appendChild</span>(script);</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="title function_">jsonp</span>(<span class="string">&#x27;http://qq.com:8888/friends.js&#x27;</span>)</span><br><span class="line">    .<span class="title function_">then</span>(<span class="function">(<span class="params">data</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(data);</span><br><span class="line">    &#125;)</span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// server.js</span></span><br><span class="line"><span class="keyword">else</span> <span class="keyword">if</span> (path === <span class="string">&#x27;/friends.js&#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (request.<span class="property">headers</span>[<span class="string">&#x27;referer&#x27;</span>].<span class="title function_">indexOf</span>(<span class="string">&#x27;http://hacker.com:9999&#x27;</span>) === <span class="number">0</span>) &#123;</span><br><span class="line">            response.<span class="property">statusCode</span> = <span class="number">200</span></span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(query.<span class="property">functionName</span>);</span><br><span class="line">            response.<span class="title function_">setHeader</span>(<span class="string">&#x27;Content-Type&#x27;</span>, <span class="string">&#x27;text/javascript;charset=utf-8&#x27;</span>)</span><br><span class="line">            <span class="keyword">const</span> string = <span class="string">`window[&#x27;&#123;&#123; xxx &#125;&#125;&#x27;]( &#123;&#123; data &#125;&#125; )`</span></span><br><span class="line">            <span class="keyword">const</span> data = fs.<span class="title function_">readFileSync</span>(<span class="string">&#x27;./public/friends.json&#x27;</span>).<span class="title function_">toString</span>()</span><br><span class="line">            response.<span class="title function_">write</span>(string.<span class="title function_">replace</span>(<span class="string">&#x27;&#123;&#123; data &#125;&#125;&#x27;</span>, data).<span class="title function_">replace</span>(<span class="string">`&#123;&#123; xxx &#125;&#125;`</span>, query.<span class="property">callback</span>))</span><br><span class="line">            response.<span class="title function_">end</span>()</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            response.<span class="property">statusCode</span> = <span class="number">404</span>;</span><br><span class="line">            response.<span class="title function_">end</span>();</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>

<hr>
<p>JSONP 的本质是前后端的协作，即前端把想要的资源以及后续的处理都告诉后台，后台封装好返回给前端执行。</p>
<p>优质博客：</p>
<p><a target="_blank" rel="noopener" href="https://segmentfault.com/a/1190000015597029">不要再问我跨域的问题了</a></p>
<p><a target="_blank" rel="noopener" href="https://segmentfault.com/a/1190000009624849#comment-area">同源策略于JS跨域（JSONP，CORD）</a></p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/09/07/35/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/lion.jpg">
      <meta itemprop="name" content="Xiaolong">
      <meta itemprop="description" content="Never stop learning">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Xiaolong's Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/09/07/35/" class="post-title-link" itemprop="url">JS函数的执行时机</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Posted on</span>

      <time title="Created: 2021-09-07 23:50:35" itemprop="dateCreated datePublished" datetime="2021-09-07T23:50:35+08:00">2021-09-07</time>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h2 id="思考"><a href="#思考" class="headerlink" title="思考"></a>思考</h2><p>代码为什么会打印 6 个 6</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> i = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">for</span>(i = <span class="number">0</span>; i &lt; <span class="number">6</span>; i++) &#123;</span><br><span class="line">	<span class="built_in">setTimeout</span>( <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(i)</span><br><span class="line">    &#125;, <span class="number">0</span>);</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<h3 id="分析"><a href="#分析" class="headerlink" title="分析"></a>分析</h3><p>在上面代码中，for 循环是同步代码，setTimeout 是异步代码，JS 按照从上到下的执行顺序执行同步代码，而异步代码被插入到任务队列中。</p>
<p>当执行完同步代码（for 循环），JS 会去执行异步代码（setTimeout）。</p>
<p>在每次 for 循环中，都将异步代码（setTimeout）放入任务队列中，所以任务队列中有 6 个 setTimeout 即有 6 个 <code>console.log(i)</code>。</p>
<p>在每次 for 循环中将 setTimeout 里的代码 <code>console.log(i)</code> 放入任务队列时，i 的值是不一样的，当 JS 引擎开始执行任务队列中代码时，会在当前作用域中找变量 i ，但当前 for 循环的作用域中没有对变量 i 的进行定义，这个时候会在创造该函数的作用域中寻找 i，找到的是 let i，这时的 i 时全局变量，并且值已经确定为 6。所以打印出 6 个 6。</p>
<p>执行流程：</p>
<p><code>for(i=0) ==&gt; for(i=1) ==&gt; for(i=2) ==&gt; for(i=3) ==&gt; for(i=4) ==&gt; for(i=5) ==&gt; for(i=6) ==&gt; console.log(6)x6</code></p>
<h3 id="解决方法一-let"><a href="#解决方法一-let" class="headerlink" title="解决方法一 let"></a>解决方法一 let</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>( <span class="keyword">let</span> i = <span class="number">0</span>; i &lt; <span class="number">6</span>; i++ )&#123;</span><br><span class="line">    <span class="built_in">setTimeout</span>( <span class="function">()=&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(i);</span><br><span class="line">    &#125;, <span class="number">0</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>let 的作用域是块作用域，能作用到 for 循环的子块中。</p>
<p>let 的作用于是块作用域，所以 setTimeout 被放到 任务队列的同时，<strong>let 定义的 i 值 也会跟随 setTimeout 进入队列</strong>。所以每次循环后队列里的 setTimeout 里的 i 值是不一样的。而 var 定义的 i 是无法进入的。（浅显易懂）</p>
<p>for 循环头部的 let 不仅将 i 绑定到 for 循环中，事实上它将其重新绑定到循环体的每一次迭代中，确保上一次迭代结束的值被重新赋值。setTimeout 里面的函数属于一个新的域，通过 var 定义的变量或全局变量是无法传入到这个函数执行，通过使用 let 来声明块变量能作用于这个块，所以箭头函数就能使用 i 这个变量，所以每次的 i 值不一样。</p>
<h3 id="解决方法二-使用立即执行函数，即闭包"><a href="#解决方法二-使用立即执行函数，即闭包" class="headerlink" title="解决方法二 使用立即执行函数，即闭包"></a>解决方法二 使用立即执行函数，即闭包</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> i = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">for</span>( i = <span class="number">0</span>; i &lt; <span class="number">6</span>; i++)&#123;</span><br><span class="line">    (<span class="keyword">function</span> (<span class="params">j</span>)&#123;</span><br><span class="line">        <span class="built_in">setTimeout</span>( <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(j);</span><br><span class="line">   		&#125;, <span class="number">0</span>);</span><br><span class="line">    &#125;)(i);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>因为 setTimeout 是异步执行，所以让它立即执行就可以了。</p>
<p>通过闭包，将 i 的变量驻留在内存中，当输出 j 时，引用的是外部函数的变量值 i，i 的值是根据循环来的，执行 setTimeout 时已经确定了里面的的输出了。</p>
<h3 id="解决方法三-setTimeout-第三个参数"><a href="#解决方法三-setTimeout-第三个参数" class="headerlink" title="解决方法三 setTimeout 第三个参数"></a>解决方法三 setTimeout 第三个参数</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> i = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; <span class="number">6</span>; i++)&#123;</span><br><span class="line">    <span class="built_in">setTimeout</span>( <span class="function">(<span class="params">i</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(i);</span><br><span class="line">    &#125;, <span class="number">0</span>, i);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 将每次的 i 值传入作用域。</span></span><br></pre></td></tr></table></figure>



<h3 id="解决方法四-try-catch"><a href="#解决方法四-try-catch" class="headerlink" title="解决方法四 try catch"></a>解决方法四 try catch</h3><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> i = <span class="number">0</span>;</span><br><span class="line"><span class="keyword">for</span>(i = <span class="number">0</span>; i &lt; <span class="number">6</span>; i++)&#123;</span><br><span class="line">    <span class="keyword">try</span>&#123;</span><br><span class="line">        <span class="keyword">throw</span> i</span><br><span class="line">    &#125;<span class="keyword">catch</span>(i)&#123;</span><br><span class="line">        <span class="built_in">setTimeout</span>( <span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(i)</span><br><span class="line">        &#125;, <span class="number">0</span>);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 将 i 作为异常抛出，传递给 setTimeout</span></span><br></pre></td></tr></table></figure>





<h2 id="JS执行机制"><a href="#JS执行机制" class="headerlink" title="JS执行机制"></a>JS执行机制</h2><p>首先，JS是单线程环境，代码从上到下依次执行。这种执行方这也被称作是“同步执行”。（同一时间 JS 只能执行一段代码，如果这段代码要执行很长时间，那么之后的代码只能尽情地等待它执行完才能执行）。</p>
<p>但 JS 中引进了异步机制。于是，所有任务可以分成两种，一种是同步任务（synchronous），另一种是异步任务（asynchronous）。</p>
<p><strong>同步任务</strong>指的是，在主线程上排队执行的任务，只有前一个任务执行完毕，才能执行后一个任务；</p>
<p><strong>异步任务</strong>指的是，不进入主线程、而进入”任务队列”（task queue）的任务，只有主线程上的任务执行完了，才通知”任务队列”，任务队列中的任务才会进入主线程执行。</p>
<h2 id="执行栈"><a href="#执行栈" class="headerlink" title="执行栈"></a>执行栈</h2><p>当执行某个函数、用户点击一次鼠标，Ajax完成，一个图片加载完成等事件发生时，只要指定过回调函数，这些事件发生时就会进入任务队列中，等待主线程读取,遵循先进先出原则。</p>
<p>执行任务队列中的某个任务，这个被执行的任务就称为执行栈。</p>
<h2 id="主线程"><a href="#主线程" class="headerlink" title="主线程"></a>主线程</h2><p>要明确的一点是，主线程跟执行栈是不同概念，主线程规定现在执行执行栈中的哪个事件。</p>
<p>主线程循环：即主线程会不停的从执行栈中读取事件，会执行完所有栈中的同步代码。</p>
<p>当遇到一个异步事件后，并不会一直等待异步事件返回结果，而是会将这个事件挂在与执行栈不同的队列中，我们称之为任务队列(Task Queue)。</p>
<p><strong>当主线程将执行栈中所有的代码执行完之后，主线程将会去查看任务队列是否有任务</strong>。如果有，那么主线程会依次执行那些任务队列中的回调函数。</p>
<h2 id="JS-异步执行的运行机制"><a href="#JS-异步执行的运行机制" class="headerlink" title="JS 异步执行的运行机制"></a>JS 异步执行的运行机制</h2><ol>
<li>所有任务都在主线程上执行，形成一个执行栈。</li>
<li>主线程之外，还存在一个任务队列。只要异步任务有了运行结果，就在任务队列之中放置一个事件。</li>
<li>一旦执行栈中的所有同步任务执行完毕，系统就会读取任务队列。那些对应的异步任务，进入执行栈开始执行。</li>
<li>主线程不断重复上面的第三步。</li>
</ol>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




    


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/09/07/36/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/lion.jpg">
      <meta itemprop="name" content="Xiaolong">
      <meta itemprop="description" content="Never stop learning">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Xiaolong's Blog">
    </span>
      <header class="post-header">
        <h2 class="post-title" itemprop="name headline">
          <a href="/2021/09/07/36/" class="post-title-link" itemprop="url">异步与Promise</a>
        </h2>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">Posted on</span>

      <time title="Created: 2021-09-07 12:24:36" itemprop="dateCreated datePublished" datetime="2021-09-07T12:24:36+08:00">2021-09-07</time>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
          <h2 id="异步"><a href="#异步" class="headerlink" title="异步"></a>异步</h2><ul>
<li><p><strong>如果能直接拿到将结果</strong></p>
<p>那就是同步</p>
<p>比如你在医院挂号，你拿到号才会离开窗口</p>
<p>同步任务可能消耗 10 毫秒，也可能需要 3 秒</p>
<p>总之不拿到结果你是不会离开的，这就是同步</p>
</li>
<li><p><strong>如果不能直接拿到结果</strong></p>
<p>那就异步</p>
<p>比如你在餐厅门口等位，你拿到号后可以去干别的事比如逛街</p>
<p>你可以每 10 分钟取餐厅问一下排到自己了没（轮询）</p>
<p>也可以扫码用微信接受通知（回调）</p>
</li>
</ul>
<h2 id="异步举例"><a href="#异步举例" class="headerlink" title="异步举例"></a>异步举例</h2><ul>
<li><p><strong>以 AJAX 为例</strong></p>
<p><code>request.send()</code> 之后，并不能直接得到 response</p>
<p>用 <code>console.log(request.response)</code> 试试</p>
<p>必须等到 readyState 变为 4 后，浏览器才会<strong>回头调用</strong> <code>request.onreadystatechange</code> 函数</p>
<p>我们才能得到 <code>request.response</code></p>
<p>这就跟餐厅给你发微信提醒的过程类似</p>
</li>
<li><p><strong>回调 callback</strong></p>
<p>你写给自己用的函数，不是回调</p>
<p>你写给别人用的函数，就是回调</p>
<p><code>request.onreadystatechange</code> 就是写个浏览器调用的</p>
<p>意思是你（浏览器）回头调用一下这个函数</p>
</li>
<li><p>简单来理解就是：同步按你的代码顺序执行，异步不按照代码顺序执行，异步的执行效率更高。</p>
</li>
</ul>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">getJSON.<span class="property">onclick</span> = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> request = <span class="keyword">new</span> <span class="title class_">XMLHttpRequest</span>();</span><br><span class="line">    request.<span class="title function_">open</span>(<span class="string">&#x27;GET&#x27;</span>, <span class="string">&#x27;/5.json&#x27;</span>);</span><br><span class="line">    request.<span class="property">onreadystatechange</span> = <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (request.<span class="property">readyState</span> === <span class="number">4</span> &amp;&amp; request.<span class="property">status</span> === <span class="number">200</span>) &#123;</span><br><span class="line">            <span class="keyword">const</span> object = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(request.<span class="property">response</span>);</span><br><span class="line">            myName.<span class="property">textContent</span> = object.<span class="property">name</span>;</span><br><span class="line">	        <span class="variable language_">console</span>.<span class="title function_">log</span>(request.<span class="property">response</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    request.<span class="title function_">send</span>();</span><br><span class="line">    <span class="comment">// console.log(request.resopne)</span></span><br><span class="line">    <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(request.<span class="property">response</span>);</span><br><span class="line">        <span class="comment">// 或者将 放在 request.onreadystatechange 函数中</span></span><br><span class="line">    &#125;, <span class="number">2000</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// request.send()执行完，再执行 request.onreadystatechange 函数</span></span><br><span class="line"><span class="comment">// 执行顺序为 response.open() =&gt; respone.send() =&gt; request.onreadystatechange</span></span><br></pre></td></tr></table></figure>

<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/kis_wuyan/article/details/116231729">onreadystatechange 执行两次</a></p>
<h2 id="回调"><a href="#回调" class="headerlink" title="回调"></a>回调</h2><p>写了却不调用，给别人调用的函数，就是回调。需自行意会</p>
<p>函数例子：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">f1</span>(<span class="params"></span>) &#123;&#125;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">f2</span>(<span class="params">fn</span>) &#123;</span><br><span class="line">    <span class="title function_">fn</span>()</span><br><span class="line">&#125;</span><br><span class="line"><span class="title function_">f2</span>(f1)</span><br></pre></td></tr></table></figure>

<p>分析：</p>
<ol>
<li>我调用 f1 没有？</li>
<li>我把 f1 传给 f2 （别人）了没有？</li>
<li>f2 调用 f1 了没有？</li>
</ol>
<p>答：1. 调用了。2.穿了。3.f2 调用了 f1。</p>
<p>那么，f1 是不是我写给 f2 调用的函数？ 是。</p>
<p>所以，f1 是回调。</p>
<hr>


<p>例子2：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">f1</span>(<span class="params">x</span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(x)</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">function</span> <span class="title function_">f2</span>(<span class="params">fn</span>)&#123;</span><br><span class="line">    <span class="title function_">fn</span>(<span class="string">&#x27;hello&#x27;</span>)</span><br><span class="line">&#125;</span><br><span class="line"><span class="title function_">f2</span>(f1)</span><br><span class="line"><span class="comment">// hello</span></span><br></pre></td></tr></table></figure>

<p>fn(‘hello’) 中的 fn 就是 f1 。</p>
<p>fn(’hello‘) 中的 ’hello’ 会被赋值给参数 x 。</p>
<p>所以 x 就是 ‘hello’。</p>
<h2 id="异步和回调的关系"><a href="#异步和回调的关系" class="headerlink" title="异步和回调的关系"></a>异步和回调的关系</h2><ul>
<li><p><strong>关联</strong></p>
<p>异步任务需要再得到结果时通知 JS 来拿结果</p>
<p>怎么通知？</p>
<p>可以让 JS 留一个函数地址给浏览器（电话号码）</p>
<p>异步任务完成时浏览器调用该函数即可（拨打电话）</p>
<p>同时把任务作为参数传给该函数（通知）</p>
<p>这个函数是我写给浏览器调用的，所以是回调函数</p>
</li>
<li><p><strong>区别</strong></p>
<p>异步任务需要用到回调函数来通知结果</p>
<p>但回调函数不一定只用在异步任务里</p>
<p>回调可以用到同步任务里</p>
<p><code>array.forEach(n=&gt;console.log(n))</code> 就是同步回调</p>
</li>
</ul>
<h2 id="判断同步异步"><a href="#判断同步异步" class="headerlink" title="判断同步异步"></a>判断同步异步</h2><p>如果一个函数的返回值处于</p>
<ul>
<li>setTimeout</li>
<li>AJAX（即 XMLHttpRequest）</li>
<li>AddEventListener</li>
</ul>
<p>这三个东西内部中，那么这个函数就是异步函数</p>
<p>还有其他 API 是异步的，遇到再说。</p>
<p>举例说明：</p>
<p>摇骰子, 随机打印出1-6 中的一个数</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> 摇骰子() &#123;</span><br><span class="line">  <span class="built_in">setTimeout</span>( <span class="function">() =&gt;</span> &#123; <span class="comment">// 箭头函数</span></span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">parseInt</span>(<span class="title class_">Math</span>.<span class="title function_">random</span>() * <span class="number">6</span>) + <span class="number">1</span>;</span><br><span class="line">  &#125;, <span class="number">1000</span>)</span><br><span class="line">  <span class="comment">// return undefined</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>分析：</p>
<p><code> 摇骰子（）</code> 里没有写 return，那就是 return undefined</p>
<p>箭头函数里有 return，返回真正结果</p>
<p>所以这是一个异步函数/异步任务。</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> n = 摇骰子();</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(n)</span><br></pre></td></tr></table></figure>

<p>如何拿到异步结果？</p>
<p>用回调，写个函数，然后把函数地址给他</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">f1</span>(<span class="params">x</span>) &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(x);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 然后要求 摇骰子函数 得到结果后 把结果作为参数 传给f1</span></span><br><span class="line"><span class="keyword">function</span> 摇骰子(fn)&#123;</span><br><span class="line">    <span class="built_in">setTimeout</span>( <span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="title function_">fn</span>(<span class="built_in">parseInt</span>(<span class="title class_">Math</span>.<span class="title function_">random</span>() * <span class="number">6</span>) + <span class="number">1</span>)</span><br><span class="line">    &#125;, <span class="number">1000</span>)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">摇骰子(f1); <span class="comment">// 结果</span></span><br></pre></td></tr></table></figure>

<p>简化为箭头函数</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">f1</span>(<span class="params">x</span>) &#123; </span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(x);</span><br><span class="line">&#125;</span><br><span class="line">摇骰子(f1);</span><br><span class="line"><span class="comment">// 改为</span></span><br><span class="line">摇骰子(<span class="function"><span class="params">x</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(x);</span><br><span class="line">&#125;);</span><br><span class="line"><span class="comment">// 再简化为</span></span><br><span class="line">摇骰子(<span class="variable language_">console</span>.<span class="property">log</span>);</span><br><span class="line"><span class="comment">// 如果参数个数不一致就不能这样简化，有个相关面试题</span></span><br></pre></td></tr></table></figure>

<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 面试题</span></span><br><span class="line"><span class="keyword">const</span> array = [<span class="string">&#x27;1&#x27;</span>, <span class="string">&#x27;2&#x27;</span>, <span class="string">&#x27;3&#x27;</span>].<span class="title function_">map</span>(<span class="built_in">parseInt</span>);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(array);</span><br><span class="line"><span class="comment">// 结果为 [1, NaN, NaN]</span></span><br><span class="line"><span class="comment">// parseInt(&#x27;1&#x27;, 0, arr) =&gt; 1</span></span><br><span class="line"><span class="comment">// parseInt(&#x27;2&#x27;, 1, arr) =&gt; NaN</span></span><br><span class="line"><span class="comment">// parseInt(&#x27;3&#x27;, 2, arr) =&gt; NaN</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> array = [<span class="string">&#x27;1&#x27;</span>, <span class="string">&#x27;2&#x27;</span> , <span class="string">&#x27;3&#x27;</span>].<span class="title function_">map</span>(<span class="function">(<span class="params">item, i , arr</span>) =&gt;</span> &#123;</span><br><span class="line">   <span class="keyword">return</span> <span class="built_in">parseInt</span>(item)</span><br><span class="line">&#125;);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(array)</span><br><span class="line"><span class="comment">// 正确结果 [1, 2, 3]</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 简写 永远使用箭头函数</span></span><br><span class="line"><span class="keyword">const</span> array = [<span class="string">&#x27;1&#x27;</span>, <span class="string">&#x27;2&#x27;</span>, <span class="string">&#x27;3&#x27;</span>].<span class="title function_">map</span>(<span class="function">(<span class="params">item</span>) =&gt;</span> <span class="built_in">parseInt</span>(item));</span><br></pre></td></tr></table></figure>



<h2 id="异步总结"><a href="#异步总结" class="headerlink" title="异步总结"></a>异步总结</h2><ul>
<li>异步任务不能拿到结果</li>
<li>于是我们传一个回调给异步任务</li>
<li>异步任务完成时调用回调</li>
<li>调用的时候把结果作为参数</li>
</ul>
<h2 id="异步任务两个结果，成功或失败"><a href="#异步任务两个结果，成功或失败" class="headerlink" title="异步任务两个结果，成功或失败"></a>异步任务两个结果，成功或失败</h2><h3 id="两个方法解决"><a href="#两个方法解决" class="headerlink" title="两个方法解决"></a>两个方法解决</h3><p><strong>方法一：回调接受两个参数</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">fs.<span class="title function_">readFile</span>(<span class="string">&#x27;./1.txt&#x27;</span>, <span class="function">(<span class="params">error, data</span>) =&gt;</span> &#123;    <span class="keyword">if</span>(error)&#123;        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&#x27;失败&#x27;</span>); <span class="keyword">return</span>;    &#125;    <span class="variable language_">console</span>.<span class="title function_">log</span>(data.<span class="title function_">toString</span>()) <span class="comment">// 成功&#125;)</span></span><br></pre></td></tr></table></figure>

<p><strong>方法二：两个回调</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">ajax</span>(<span class="string">&#x27;get&#x27;</span>, <span class="string">&#x27;/1.json&#x27;</span>, <span class="function"><span class="params">data</span> =&gt;</span> &#123;<span class="comment">/*成功回调*/</span>&#125;, <span class="function"><span class="params">error</span> =&gt;</span> &#123;<span class="comment">/*失败回调*/</span>&#125;)<span class="title function_">ajax</span>(<span class="string">&#x27;get&#x27;</span>, <span class="string">&#x27;/1.json&#x27;</span>,&#123;    <span class="attr">success</span>: <span class="function">() =&gt;</span> &#123;&#125;,    <span class="attr">fail</span>: <span class="function">() =&gt;</span> &#123;&#125;&#125;)<span class="comment">// 接受一个对象，对象有两个 key 表示成功和失败</span></span><br></pre></td></tr></table></figure>



<h3 id="这些方法的不足"><a href="#这些方法的不足" class="headerlink" title="这些方法的不足"></a>这些方法的不足</h3><p>不管方法一还是方法二，都有问题</p>
<ol>
<li>不规范，名称五花八门，有人用 success + error，有人用 success + fail，done + fail</li>
<li>容易出现==回调地狱== ，代码变得看不懂</li>
<li>很难进行错无处理</li>
</ol>
<p><strong>回调地狱举例</strong></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="title function_">getUser</span>( <span class="function"><span class="params">user</span> =&gt;</span> &#123;    <span class="title function_">getGroups</span>(user, <span class="function">(<span class="params">groups</span>) =&gt;</span> &#123;        groups.<span class="title function_">forEach</span>( <span class="function">(<span class="params">g</span>) =&gt;</span> &#123;            g.<span class="title function_">filter</span>(<span class="function"><span class="params">x</span> =&gt;</span> x.<span class="property">ownerId</span> === user.<span class="property">id</span>)            .<span class="title function_">forEach</span>(<span class="function"><span class="params">x</span> =&gt;</span> <span class="variable language_">console</span>.<span class="title function_">log</span>(x))        &#125;)    &#125;)&#125;)<span class="comment">// 仅示例，这只是四层，二十层呢，代码会很难读</span></span><br></pre></td></tr></table></figure>

<center><img src="https://cdn.jsdelivr.net/gh/Drwna/image//images/Snipaste_2021-09-25_22-12-10.png" alt="Snipaste_2021-09-25_22-12-10" width="800px"></center><center style="font-size:14px;color:#C0C0C0;text-decoration:underline"> 吐槽回调地狱 来源网络</center> 



<h3 id="如何解决回调问题，用-Promise"><a href="#如何解决回调问题，用-Promise" class="headerlink" title="如何解决回调问题，用 Promise"></a>如何解决回调问题，用 Promise</h3><p>有什么办法能解决这三个问题：</p>
<ul>
<li>会犯回调的名字或顺序</li>
<li>拒绝回调地狱，让代码可读性更强</li>
<li>很方便地捕获错误</li>
</ul>
<blockquote>
<p>1976年，Daniel P.Friedman 和 David Wis 俩人提出 Promise 思想</p>
<p>后人基于此发明了 Future、Delay、Deferred等</p>
<p>前端结合 Promise 和 JS，制定了 <a target="_blank" rel="noopener" href="https://www.ituring.com.cn/article/66566">Promise/A+规范</a></p>
<p>该规范详细描述了 Promise 的原理和使用方法。</p>
</blockquote>
<h2 id="以-AJAX-的封装为例，来解释-Promise"><a href="#以-AJAX-的封装为例，来解释-Promise" class="headerlink" title="以 AJAX 的封装为例，来解释 Promise"></a>以 AJAX 的封装为例，来解释 Promise</h2><p><a target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise MDN</a></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 示例ajax = (method, url, options) =&gt; &#123;    const &#123;success, fail&#125; = option; // 析构赋值    // const succes = option.success;    // const fail = option.fail;    const request = new XMLHttpRequest();    request.open(method, url);    request.onreadystatechange = () =&gt; &#123;        if (request.readyState === 4) &#123;            // 成功就调用 success，失败 fail            if (request.status &lt; 400) &#123;                success.call(null, request.response);            &#125;else if (request.status &gt;= 400) &#123;                fail.call(null, request, request.status);            &#125;        &#125;    &#125;    request.rend();&#125;ajax(&#x27;get&#x27;, &#x27;/xxx&#x27;, &#123;    success(response)&#123;&#125;, // function 缩写    // success: function(response)&#123;&#125;    fail: (request, status) =&gt; &#123;&#125;&#125;)</span></span><br></pre></td></tr></table></figure>



<p>Promise 写法：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 先改一下调用姿势ajax(&#x27;get&#x27;, &#x27;/xxx&#x27;, &#123;    success(response)&#123;&#125;,    fail: (request, status) =&gt; &#123;&#125;&#125;)// 上面用到了两个回调，还使用了 success 和 fail// 改成 Promise 写法ajax(&#x27;get&#x27;, &#x27;/xxx&#x27;)    .then((response)=&gt;&#123;&#125;, (request, status)=&gt;&#123;&#125; )// 虽然也是回调// 但是不需要经济 success 和 fail 了// then 的第一个参数就是 success// then 的第二个参数就是 fail</span></span><br></pre></td></tr></table></figure>

<p>请问 ajax() 返回了个啥 ？</p>
<p>返回了一个含有 .then() 方法的对象呗。</p>
<p>那么再请问如何得到这个含有 .then() 的对象呢 ？</p>
<p>那就要改造 ajax 的源码了。</p>
<p><code>return new Promise((resolve, reject) =&gt; &#123;&#125;)</code></p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 修改 ajaxajax = (method, url, option) =&gt; &#123;    return new Promise((resolve, reject) =&gt; &#123;        const &#123;success, fail&#125; = option;        const request = new XMLHttpRequest();        request.open(methon, url);        request.onreadystatechange = () =&gt; &#123;            if(request.readyState === 4) &#123;                if(request.status &lt; 400) &#123;                    // 成功                    resolve.call(null, request.response);                &#125;else if(request.status &gt;= 400) &#123;                    // s                    reject.call(null, request);                &#125;            &#125;        &#125;        request.send();    &#125;);&#125;</span></span><br></pre></td></tr></table></figure>



<p><strong>小结</strong></p>
<p>第一步：</p>
<ul>
<li><code>retrun new Promise((resolve, reject) =&gt; &#123;...&#125;)</code></li>
<li>任务成功则调用 <code>resolve(result)</code></li>
<li>任务失败则调用 <code>reject(error)</code></li>
<li>resolve 和 reject 会再去调用成功和失败函数</li>
</ul>
<p>第二步：</p>
<ul>
<li>使用 <code>.then(success, fail)</code>传入成功函数和失败函数</li>
</ul>
<hr>
<p>我们自己封装的 ajax 的缺点:</p>
<p>post 无法上传数据。request.send(这里可以上传数据)</p>
<p>不能设置请求头。request.setRequestHeader(key, value)</p>
<p>使用：</p>
<p> <a target="_blank" rel="noopener" href="https://www.jquery123.com/jQuery.ajax/">Jquery.ajax</a></p>
<p><a target="_blank" rel="noopener" href="http://www.axios-js.com/zh-cn/docs/">axios</a>(推荐)</p>

      
    </div>

    
    
    

    <footer class="post-footer">
        <div class="post-eof"></div>
      
    </footer>
  </article>
</div>




  <nav class="pagination">
    <a class="extend prev" rel="prev" href="/page/2/"><i class="fa fa-angle-left" aria-label="Previous page"></i></a><a class="page-number" href="/">1</a><a class="page-number" href="/page/2/">2</a><span class="page-number current">3</span><a class="page-number" href="/page/4/">4</a><a class="page-number" href="/page/5/">5</a><a class="extend next" rel="next" href="/page/4/"><i class="fa fa-angle-right" aria-label="Next page"></i></a>
  </nav>

</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">


<div class="copyright">
  &copy; 2021 – 
  <span itemprop="copyrightYear">2023</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Xiaolong</span>
</div>

    </div>
  </footer>

  
  <script src="https://cdn.jsdelivr.net/npm/animejs@3.2.1/lib/anime.min.js" integrity="sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY=" crossorigin="anonymous"></script>
<script src="/js/comments.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/next-boot.js"></script>

  
<script src="/js/third-party/search/local-search.js"></script>




  





</body>
</html>
